def __init__(self, block_types, **kwargs): super(StreamField, self).__init__(**kwargs) if isinstance(block_types, Block): self.stream_block = block_types elif isinstance(block_types, type): self.stream_block = block_types(required=not self.blank) else: self.stream_block = StreamBlock(block_types, required=not self.blank)
def __init__(self, block_types, **kwargs): if isinstance(block_types, Block): self.stream_block = block_types elif isinstance(block_types, type): self.stream_block = block_types() else: self.stream_block = StreamBlock(block_types) super(StreamField, self).__init__(**kwargs)
class ColumnsBlock(StructBlock): left_column = StreamBlock(BASE_BLOCKS + CONTACT_PERSON_TEASER_BLOCKS) right_column = StreamBlock(BASE_BLOCKS + CONTACT_PERSON_TEASER_BLOCKS, required=False) def get_context(self, value, parent_context=None): context = super().get_context(value, parent_context) context['left_column'] = value.get('left_column') context['right_column'] = value.get('right_column') return context class Meta: icon = 'fa fa-columns' label = 'Columns 1-1' template = None
class ColumnsBlock(StructBlock): left_column = StreamBlock(_COLUMNS_BLOCKS) right_column = StreamBlock( _COLUMNS_BLOCKS) # , form_classname='pull-right') def get_context(self, value, parent_context=None): context = super(ColumnsBlock, self).get_context(value, parent_context=parent_context) context['left_column'] = value.get('left_column') context['right_column'] = value.get('right_column') return context class Meta: icon = 'fa fa-columns' label = 'Columns 1-1' template = None
class TwoColumnBlock(StructBlock): left_column = StreamBlock([ ('heading', CharBlock(classname="full title")), ('paragraph', RichTextBlock()), ('image', ImageChooserBlock()), ], icon='arrow-left', label='Left column content') right_column = StreamBlock([ ('heading', CharBlock(classname="full title")), ('paragraph', RichTextBlock()), ('image', ImageChooserBlock()), ], icon='arrow-right', label='Right column content') class Meta: template = 'home/includes/two_column_block.html' icon = 'placeholder' label = 'Two Columns'
class Columns1To1To1To1Block(StructBlock): first_column = StreamBlock(_COLUMNS_BLOCKS) second_column = StreamBlock(_COLUMNS_BLOCKS) third_column = StreamBlock(_COLUMNS_BLOCKS) fourth_column = StreamBlock(_COLUMNS_BLOCKS) class Meta: icon = 'fa fa-columns' label = 'Columns 1:1:1:1' template = 'widgets/columns-1-1-1-1.html' def get_context(self, value, parent_context=None): context = super(Columns1To1To1To1Block, self).get_context(value, parent_context=parent_context) context['first_column'] = value.get('first_column') context['second_column'] = value.get('second_column') context['third_column'] = value.get('third_column') context['fourth_column'] = value.get('fourth_column') return context
class Columns1To1To1Block(ColumnsBlock): middle_column = StreamBlock(BASE_BLOCKS + CONTACT_PERSON_TEASER_BLOCKS) class Meta: label = 'Columns 1:1:1' template = 'widgets/columns-1-1-1.html' def get_context(self, value, parent_context=None): context = super().get_context(value, parent_context) context['middle_column'] = value.get('middle_column') return context
class Columns1To1To1Block(ColumnsBlock): center_column = StreamBlock(_COLUMNS_BLOCKS) class Meta: label = 'Columns 1:1:1' template = 'widgets/columns-1-1-1.html' def get_context(self, value): context = super().get_context(value) context['center_column'] = value.get('center_column') return context
class OneColumnBlock(StructBlock): back_image = ImageChooserBlock(blank=True) background_size = ImageFormatChoiceBlock(choices=SIZE_CHOICES,default="auto") one_column = StreamBlock([ ('heading', CharBlock(classname="full title")), ('paragraph', RichTextBlock()), ], icon='arrow-left', label='Parallax content') class Meta: template = 'home/includes/one_column_block.html' icon = 'placeholder' label = 'One Column'
class PromoParagraphBlock(ContentBlock): body = StreamBlock([('text', RichTextBlock()), ('call_to_action', ListBlock(CallToActionBlock())), ('spacer', ChoiceBlock(choices=[('15', '15 pixels'), ('30', '30 pixels'), ('45', '45 pixels'), ('60', '60 pixels'), ('75', '75 pixels'), ('90', '90 pixels')], required=False))]) class Meta: template = 'blocks/promo_paragraph.html' icon = 'doc-full'
class DSFModulesBlock(StructBlock): module_1_title = CharBlock() module_1 = StreamBlock(DSF_BLOCKS) module_2_title = CharBlock() module_2 = StreamBlock(DSF_BLOCKS) module_3_title = CharBlock() module_3 = StreamBlock(DSF_BLOCKS) module_4_title = CharBlock() module_4 = StreamBlock(DSF_BLOCKS) module_5_title = CharBlock() module_5 = StreamBlock(DSF_BLOCKS) module_6_title = CharBlock() module_6 = StreamBlock(DSF_BLOCKS) module_7_title = CharBlock() module_7 = StreamBlock(DSF_BLOCKS) def get_context(self, value, parent_context=None): context = super().get_context(value, parent_context) modules = { 1: { 'content': value.get('module_1'), 'color': '#403D38', 'text': value.get('module_1_title') }, # _('Operational Strategy and Action plan') 2: { 'content': value.get('module_2'), 'color': '#6E3237', 'text': value.get('module_2_title') }, # _('National and Subnational Level') 3: { 'content': value.get('module_3'), 'color': '#604F3B', 'text': value.get('module_3_title') }, # _('Landscape Level')} 4: { 'content': value.get('module_4'), 'color': '#3B482E', 'text': value.get('module_4_title') }, # _('Sea Level') 5: { 'content': value.get('module_5'), 'color': '#22454E', 'text': value.get('module_5_title') }, # _('SLM Territorial Planning') 6: { 'content': value.get('module_6'), 'color': '#2D446B', 'text': value.get('module_6_title') }, # _('Implementation and scaling out') 7: { 'content': value.get('module_7'), 'color': '#3A3451', 'text': value.get('module_7_title') }, # _('Knowledge management platform for informed decision making') } sections = [] sidebar_links = [] for i in range(1, 8): module = modules.get(i) content = module.get('content') if not content: continue # Do not add this section if there is no content. sections.append({ 'content': module.get('content'), 'id': 'module-{0}'.format(i), 'module_id': i, }) sidebar_links.append({ 'anchorlink': True, 'color': 'white', 'backgroundcolor': module.get('color'), 'href': '#module-{0}'.format(i), 'kicker': 'Module {0}'.format(i), 'text': module.get('text'), }) can_upload_documents = False page = context.get('page') if page: can_upload_documents = page.permissions_for_user( context['request'].user).can_edit() context.update({ 'sections': sections, 'sidebar_links': sidebar_links, 'context': context, 'can_upload_documents': can_upload_documents, }) return context class Meta: icon = 'fa fa-th-list' label = 'DSF Modules' template = 'widgets/tab-infobox.html'
class StreamField(with_metaclass(models.SubfieldBase, models.Field)): def __init__(self, block_types, **kwargs): if isinstance(block_types, Block): self.stream_block = block_types elif isinstance(block_types, type): self.stream_block = block_types() else: self.stream_block = StreamBlock(block_types) super(StreamField, self).__init__(**kwargs) def get_internal_type(self): return 'TextField' def get_panel(self): from wagtail.wagtailadmin.edit_handlers import StreamFieldPanel return StreamFieldPanel def deconstruct(self): name, path, _, kwargs = super(StreamField, self).deconstruct() block_types = self.stream_block.child_blocks.items() args = [block_types] return name, path, args, kwargs def to_python(self, value): if value is None or value == '': return StreamValue(self.stream_block, []) elif isinstance(value, StreamValue): return value elif isinstance(value, string_types): try: unpacked_value = json.loads(value) except ValueError: # value is not valid JSON; most likely, this field was previously a # rich text field before being migrated to StreamField, and the data # was left intact in the migration. Return an empty stream instead # (but keep the raw text available as an attribute, so that it can be # used to migrate that data to StreamField) return StreamValue(self.stream_block, [], raw_text=value) if unpacked_value is None: # we get here if value is the literal string 'null'. This should probably # never happen if the rest of the (de)serialization code is working properly, # but better to handle it just in case... return StreamValue(self.stream_block, []) return self.stream_block.to_python(unpacked_value) else: # See if it looks like the standard non-smart representation of a # StreamField value: a list of (block_name, value) tuples try: [None for (x, y) in value] except (TypeError, ValueError): # Give up trying to make sense of the value raise TypeError( "Cannot handle %r (type %r) as a value of StreamField" % (value, type(value))) # Test succeeded, so return as a StreamValue-ified version of that value return StreamValue(self.stream_block, value) def get_prep_value(self, value): if isinstance( value, StreamValue) and not (value) and value.raw_text is not None: # An empty StreamValue with a nonempty raw_text attribute should have that # raw_text attribute written back to the db. (This is probably only useful # for reverse migrations that convert StreamField data back into plain text # fields.) return value.raw_text else: return json.dumps(self.stream_block.get_prep_value(value), cls=DjangoJSONEncoder) def formfield(self, **kwargs): """ Override formfield to use a plain forms.Field so that we do no transformation on the value (as distinct from the usual fallback of forms.CharField, which transforms it into a string). """ defaults = {'form_class': BlockField, 'block': self.stream_block} defaults.update(kwargs) return super(StreamField, self).formfield(**defaults) def value_to_string(self, obj): value = self.value_from_object(obj) return self.get_prep_value(value) def get_searchable_content(self, value): return self.stream_block.get_searchable_content(value) def check(self, **kwargs): errors = super(StreamField, self).check(**kwargs) errors.extend(self.stream_block.check(field=self, **kwargs)) return errors
class StreamField(with_metaclass(models.SubfieldBase, models.Field)): def __init__(self, block_types, **kwargs): if isinstance(block_types, Block): self.stream_block = block_types elif isinstance(block_types, type): self.stream_block = block_types() else: self.stream_block = StreamBlock(block_types) super(StreamField, self).__init__(**kwargs) def get_internal_type(self): return 'TextField' def get_panel(self): from wagtail.wagtailadmin.edit_handlers import StreamFieldPanel return StreamFieldPanel def deconstruct(self): name, path, _, kwargs = super(StreamField, self).deconstruct() block_types = self.stream_block.child_blocks.items() args = [block_types] return name, path, args, kwargs def to_python(self, value): if value is None or value == '': return StreamValue(self.stream_block, []) elif isinstance(value, StreamValue): return value else: # assume string try: unpacked_value = json.loads(value) except ValueError: # value is not valid JSON; most likely, this field was previously a # rich text field before being migrated to StreamField, and the data # was left intact in the migration. Return an empty stream instead. # TODO: keep this raw text data around as a property of the StreamValue # so that it can be retrieved in data migrations return StreamValue(self.stream_block, []) if unpacked_value is None: # we get here if value is the literal string 'null'. This should probably # never happen if the rest of the (de)serialization code is working properly, # but better to handle it just in case... return StreamValue(self.stream_block, []) return self.stream_block.to_python(unpacked_value) def get_prep_value(self, value): return json.dumps(self.stream_block.get_prep_value(value), cls=DjangoJSONEncoder) def formfield(self, **kwargs): """ Override formfield to use a plain forms.Field so that we do no transformation on the value (as distinct from the usual fallback of forms.CharField, which transforms it into a string). """ defaults = {'form_class': BlockField, 'block': self.stream_block} defaults.update(kwargs) return super(StreamField, self).formfield(**defaults) def value_to_string(self, obj): value = self._get_val_from_obj(obj) return self.get_prep_value(value) def get_searchable_content(self, value): return self.stream_block.get_searchable_content(value)
class StreamField(with_metaclass(models.SubfieldBase, models.Field)): def __init__(self, block_types, **kwargs): if isinstance(block_types, Block): self.stream_block = block_types elif isinstance(block_types, type): self.stream_block = block_types() else: self.stream_block = StreamBlock(block_types) super(StreamField, self).__init__(**kwargs) def get_internal_type(self): return 'TextField' def get_panel(self): from wagtail.wagtailadmin.edit_handlers import StreamFieldPanel return StreamFieldPanel def deconstruct(self): name, path, _, kwargs = super(StreamField, self).deconstruct() block_types = self.stream_block.child_blocks.items() args = [block_types] return name, path, args, kwargs def to_python(self, value): if value is None or value == '': return StreamValue(self.stream_block, []) elif isinstance(value, StreamValue): return value elif isinstance(value, string_types): try: unpacked_value = json.loads(value) except ValueError: # value is not valid JSON; most likely, this field was previously a # rich text field before being migrated to StreamField, and the data # was left intact in the migration. Return an empty stream instead # (but keep the raw text available as an attribute, so that it can be # used to migrate that data to StreamField) return StreamValue(self.stream_block, [], raw_text=value) if unpacked_value is None: # we get here if value is the literal string 'null'. This should probably # never happen if the rest of the (de)serialization code is working properly, # but better to handle it just in case... return StreamValue(self.stream_block, []) return self.stream_block.to_python(unpacked_value) else: # See if it looks like the standard non-smart representation of a # StreamField value: a list of (block_name, value) tuples try: [None for (x, y) in value] except (TypeError, ValueError): # Give up trying to make sense of the value raise TypeError("Cannot handle %r (type %r) as a value of StreamField" % (value, type(value))) # Test succeeded, so return as a StreamValue-ified version of that value return StreamValue(self.stream_block, value) def get_prep_value(self, value): if isinstance(value, StreamValue) and not(value) and value.raw_text is not None: # An empty StreamValue with a nonempty raw_text attribute should have that # raw_text attribute written back to the db. (This is probably only useful # for reverse migrations that convert StreamField data back into plain text # fields.) return value.raw_text else: return json.dumps(self.stream_block.get_prep_value(value), cls=DjangoJSONEncoder) def formfield(self, **kwargs): """ Override formfield to use a plain forms.Field so that we do no transformation on the value (as distinct from the usual fallback of forms.CharField, which transforms it into a string). """ defaults = {'form_class': BlockField, 'block': self.stream_block} defaults.update(kwargs) return super(StreamField, self).formfield(**defaults) def value_to_string(self, obj): value = self.value_from_object(obj) return self.get_prep_value(value) def get_searchable_content(self, value): return self.stream_block.get_searchable_content(value) def check(self, **kwargs): errors = super(StreamField, self).check(**kwargs) errors.extend(self.stream_block.check(field=self, **kwargs)) return errors