2017-12-11 16 views
0

オンページナビゲーションのためにサイドバーのナビゲーション付きの長いスクロールページを作成する必要があります。これは、各見出しにIDが付くことを意味します。ストリームフィールドレベルで検証して、ユーザーが重複したIDを入れないようにすることはできますか?ストリームフィールドに重複がないことを確認します

編集:
見出しは、次のような定義されています。

class HeadingOneBlock(blocks.StructBlock): 
    id = blocks.RegexBlock(regex=r'^\S*$', help_text='No spaces or special characters') 
    heading = blocks.CharBlock() 

    class Meta: 
     template = 'base/heading_one.html' 
     icon = 'title' 
     label = 'h1' 

とページ:

class LongScrollPage(Page): 
    banner_text = RichTextField() 
    description = RichTextField() 
    body = StreamField([ 
     ('heading1', HeadingOneBlock()), 
     ('heading2', HeadingTwoBlock()), 
     ('paragraph', blocks.RichTextBlock(features=['bold', 'italic', 'ol', 'ul', 'link', 'image', 'hr'])), 
     ('collapsible_panel', CollapsiblePanelBlock()), 
     ('table', TableBlock(template='base/tables.html')), 
    ], blank=True, null=True) 

    content_panels = Page.content_panels + [ 
     FieldPanel('banner_text'), 
     FieldPanel('description'), 
     StreamFieldPanel('body'), 
    ] 

は '身体' レベルで検証する方法はありますか?私はブロックレベルで検証することができますが、どのようにidsが一意であることを確認するのですか?

+0

ます。たとえば、この質問に少しより多くの情報を入れてもらえますが、これまで使用しているコードを使用して、BakeryDemo、セキレイ1.13でこれをテストしています。 –

答えて

0

これを解決する方法の1つは、StreamFieldのカスタムvalidatorsです。

詳しくはDjango Form Validationをご覧ください。

また、バリデータに提示されるvalueは、[StreamValue](https://github.com/wagtail/wagtail/blob/master/wagtail/core/blocks/stream_block.py#L324)のインスタンスであり、タプルのリストを含むstream_dataという属性を持っています。各タプルの最初の項目は、ブロックに与えたラベルです(例ではheading1、heading2、paragraph)。 2番目の項目はStructValueのインスタンスで、各サブブロックの値は下の例​​のhence data[1].get('id')のキーでアクセスできます。

検証コード(またあなたのmodels.pyファイルにすることができます):

from django.core.exceptions import ValidationError 
from wagtail.core.blocks import StreamBlockValidationError # plus all blocks imported here 


def validate_ids_in_headings(value): 
    # value.stream_data is a list of tuples 
    # first item in each tuple is the label (eg. 'heading1' or 'paragraph') 
    # second item in each tuple is a StructValue which is like an ordered dict 
    items = [ 
     data[1].get('id') 
     for data in value.stream_data 
     if 'heading' in data[0] 
    ] 
    if len(set(items)) != len(items): 
     # sets can only be unique so - the items are are not unique 
     # must raise special StreamBlockValidationError error like this 
     raise StreamBlockValidationError(
      non_block_errors=ValidationError(
       'All headings must have unique ID values: %(value)s', 
       code='invalid', 
       params={'value': items}, 
      ) 
     ) 
    # if valid, do nothing 

改訂モデルコード:

# using one HeadingBlock class here as you can define template/label within the StreamField 
class HeadingBlock(StructBlock): 
    id = RegexBlock(regex=r'^\S*$', help_text='No spaces or special characters') 
    heading = CharBlock() 
    class Meta: 
     icon = 'title' 


body = StreamField([ 
    ('heading1', HeadingBlock(label='h1', template='base/heading_one.html')), # note: label/template set here 
    ('heading2', HeadingBlock(label='h2', template='base/heading_two.html')), # note: label/template set here 
    ('paragraph', RichTextBlock(features=['bold', 'italic', 'ol', 'ul', 'link', 'image', 'hr'])), 
    ('collapsible_panel', CollapsiblePanelBlock()), 
    ('table', TableBlock(template='base/tables.html')), 
# validators set here, must be within a list - even if one item, removed null=True as not needed 
], blank=True, validators=[validate_ids_in_headings]) 

これは、ユーザーに表示されるエラーがスローされます。

残念ながら、これはタブ(エラーインジケータ付き)を強調表示しませんが、特定のエラーテキストを含む 'Body'ブロックの先頭にエラーを表示します。Issue 4122を参照してください。

私は、Python 3

+0

ありがとう! – jeffreyb

関連する問題