def test_custom_editor_in_rich_text_block(self): block = RichTextBlock(editor='custom') form_html = block.render_form(block.to_python("<p>hello</p>"), 'body') # Check that the custom plugin options are being passed in the hallo initialiser self.assertIn('makeHalloRichTextEditable("body", {"halloheadings": {"formatBlocks": ["p", "h2"]}});', form_html)
def test_features_list_on_rich_text_block(self): block = RichTextBlock(features=['blockquote', 'embed', 'made-up-feature']) form_html = block.render_form(block.to_python("<p>hello</p>"), 'body') # Check that the custom plugin options are being passed in the hallo initialiser self.assertIn('"halloblockquote":', form_html) self.assertIn('"hallowagtailembeds":', form_html) self.assertNotIn('"hallolists":', form_html) self.assertNotIn('"hallowagtailimage":', form_html) # check that media (js/css) from the features is being imported media_html = str(block.media) self.assertIn('testapp/js/hallo-blockquote.js', media_html) self.assertIn('testapp/css/hallo-blockquote.css', media_html) # check that we're NOT importing media for the default features we're not using self.assertNotIn('wagtaildocs/js/hallo-plugins/hallo-wagtaildoclink.js', media_html)
class HomePagesStreamBlock(StreamBlock): paragraph = RichTextBlock(icon="pilcrow", label=u'段落') image_list_4 = FourColImageListBlock(icon="image", label=u"四列图片") image_list_3 = ThreeColImageListBlock(icon="image", label=u"三列图片") image_list_2 = TwoColImageListBlock(icon="image", label=u"两列图片") link_list = LinkList(icon="link", label=u"链接列表") html = RawHTMLBlock(icon="code", label=u'HTML代码') overlap = OverlapDesign(icon="pilcrow", label=u"大小标题模块") quote = TextBlock(icon = "openquote", label=u'引用') image_list_5 = HPFiveColImageListBlock(icon="image", label=u"主页五列图片") carousel = Carousel(icon="image", label=u"幻灯片图片")
class AccordionBlock(StructBlock): class Meta: icon = "arrow-down-big" template = "blocks/accordion_block.html" accordion_group_title = TextBlock(required=False, blank=True, default="") accordion_items = ListBlock( StructBlock([ ('accordion_title', CharBlock(required=True)), ('accordion_content', RichTextBlock(required=True)), ]))
class DefaultStreamPage(Page): body = StreamField([ ('text', CharBlock()), ('rich_text', RichTextBlock()), ('image', ImageChooserBlock()), ], default='') content_panels = [ FieldPanel('title'), StreamFieldPanel('body'), ]
class LockedBackgroundStreamBlock(StreamBlock): section_heading = CharBlock( icon="title", classname="title", template="longform/blocks/section_heading.html") heading = CharBlock(icon="title", classname="title", template="longform/blocks/heading.html") sub_heading = CharBlock(icon="title", classname="title", template="longform/blocks/sub_heading.html") intro = RichTextBlock(icon="pilcrow", template="longform/blocks/intro.html") paragraph = RichTextBlock(icon="pilcrow", template="longform/blocks/paragraph.html") pullquote = PullQuoteBlock() html = IframeBlock(template="longform/blocks/html.html") class Meta: template = 'longform/blocks/content_stream.html'
class BaseStreamBlock(StreamBlock): """ Define the custom blocks that `StreamField` will utilize """ heading_block = HeadingBlock(label="标题", heading_text="请选择字号") paragraph_block = RichTextBlock(icon="pilcrow", template="blocks/paragraph_block.html", label=u"段落") image_block = ImageBlock(label=u"图片", icon="image") block_quote = BlockQuote(label=u"引用", ) table_block = TableBlock(label=u"表格", ) raw_html = RawHTMLBlock(icon="code", label='Raw HTML')
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 SixPolygonHeader(StructBlock): first_polygon_header = CharBlock(required=True) first_polygon_text = RichTextBlock(required=True) first_polygon_icon = ChoiceBlock(choices=ICONS, required=True) second_polygon_header = CharBlock(required=True) second_polygon_text = RichTextBlock(required=True) second_polygon_icon = ChoiceBlock(choices=ICONS, required=True) third_polygon_header = CharBlock(required=True) third_polygon_text = RichTextBlock(required=True) third_polygon_icon = ChoiceBlock(choices=ICONS, required=True) fourth_polygon_header = CharBlock(required=True) fourth_polygon_text = RichTextBlock(required=True) fourth_polygon_icon = ChoiceBlock(choices=ICONS, required=True) fifth_polygon_header = CharBlock(required=True) fifth_polygon_text = RichTextBlock(required=True) fifth_polygon_icon = ChoiceBlock(choices=ICONS, required=True) sixth_polygon_header = CharBlock(required=False) sixth_polygon_text = RichTextBlock(required=False) sixth_polygon_icon = ChoiceBlock(choices=ICONS, required=False) class Meta: image = 'pages/images/streamfield_blocks/six_polygon_header.jpg' template = 'pages/streamfield_blocks/six_polygon_header.html'
class FourColumnWithHeadingImageBlock(StructBlock): block_heading = CharBlock(required=True) image = ImageChooserBlock(required=True) first_column_heading = CharBlock(required=True) first_column_text = RichTextBlock(required=True) second_column_heading = CharBlock(required=True) second_column_text = RichTextBlock(required=True) third_column_heading = CharBlock(required=True) third_column_text = RichTextBlock(required=True) fourth_column_heading = CharBlock(required=True) fourth_column_text = RichTextBlock(required=True) read_more_button = ReadMoreButtonBlock(required=False) class Meta: image = 'pages/images/streamfield_blocks/four_columns_with_heading_image.jpg' template = 'pages/streamfield_blocks/four_columns_with_heading_image.html'
class StreamPage(Page): body = StreamField([ ('text', CharBlock()), ('rich_text', RichTextBlock()), ('image', ExtendedImageChooserBlock()), ]) api_fields = ('body', ) content_panels = [ FieldPanel('title'), StreamFieldPanel('body'), ]
class StaticPage(TemplateableMixin, PageWithHeader): subtitle = models.CharField(max_length=255, blank=True, null=True) content = StreamField( [ ('assesments_of_uses', AssesmentsOfUsesBlock()), ('community_stats', CommunityStatsBlock()), ('drivers_of_change', DriversOfChangeBlock()), ('four_columns_with_image', FourColumnWithHeadingImageBlock()), ('foresight_in_policy_cycle', ForesightInPolicyCycleBlock()), ('heading_with_image', HeadingWithImageBlock()), ('heading_with_text', HeadingWithTextBlock()), ('institutions', InstitutionsBlock()), ('methodology', MethodologyBlock()), ('polygon_header', SixPolygonHeader()), ('stakeholders', Stakeholders()), ('table_with_header', TableWithHeaderBlock()), # ('team', TeamBlock()), ('testimonials', TestimonialsBlock()), ('three_columns', ThreeColumnBlock()), ('topic_grid', TopicGridBlock()), ('paragraph', RichTextBlock( template='pages/streamfield_blocks/paragraph.html')), ('video_embed', VideoEmbedBlock()), ], blank=True) content_panels = PageWithHeader.content_panels + [ FieldPanel('subtitle'), StreamFieldPanel('content'), ] TEMPLATES_AND_CONTEXTS = ( ('pages/home_page.html', None), ('pages/foresight_dictionary.html', foresight_dictionary_get_context), ) page_template = models.CharField(choices=((k[0], k[0]) for k in TEMPLATES_AND_CONTEXTS), max_length=255, blank=True, null=True) settings_panels = PageWithHeader.settings_panels + [ MultiFieldPanel([ FieldPanel('page_template', classname="template"), ], 'Developer settings', classname='collapsible collapsed'), ]
class NexusGraph(StructBlock): block_heading = CharBlock(required=True) top_title = CharBlock(required=True) top_description = RichTextBlock(required=False) top_to_left_description = RichTextBlock(required=False) top_to_right_description = RichTextBlock(required=False) right_title = CharBlock(required=True) right_description = RichTextBlock(required=False) right_to_top_description = RichTextBlock(required=False) right_to_left_description = RichTextBlock(required=False) left_title = CharBlock(required=True) left_description = RichTextBlock(required=False) left_to_right_description = RichTextBlock(required=False) left_to_top_description = RichTextBlock(required=False) read_more_button = ReadMoreButtonBlock(required=False) class Meta: image = 'topics/images/streamfield_blocks/resources_nexus.png' template = 'topics/streamfield_blocks/nexus_graph.html'
class BaseStreamBlock(StreamBlock): """ Define the custom blocks that `StreamField` will utilize """ heading_block = HeadingBlock() paragraph_block = RichTextBlock(icon="fa-paragraph", template="blocks/paragraph_block.html") image_block = ImageBlock() block_quote = BlockQuote() embed_block = EmbedBlock( help_text= 'Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon="fa-s15", template="blocks/embed_block.html")
class ThreeColumnBlock(StructBlock): left_column = StreamBlock([ ('heading', CharBlock(classname="full title")), ('paragraph', RichTextBlock()), ('image', ImageChooserBlock()), ], icon='arrow-left', label='Left column content') center_column = StreamBlock([ ('heading', CharBlock(classname="full title")), ('paragraph', RichTextBlock()), ('image', ImageChooserBlock()), ], icon='arrow-right', label='Center 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/three_column_block.html' icon = 'placeholder' label = 'Three Columns'
class Job(ClusterableModel, index.Indexed): title = CharField(max_length=255, unique=True) background = RichTextField(blank=True) responsibilities = RichTextField(blank=True) skills = RichTextField(blank=True) notes = RichTextField(blank=True) location = RichTextField(blank=True) benefits = RichTextField(blank=True) applying = StreamField([ ('raw_html', RawHTMLBlock( help_text= 'To add Google Analytics to your link, use this template: ' '<a href="www.example.com" onclick="trackOutboundLink("www.example.com"); return false;">link</a>.' ' With great power comes great responsibility. ' 'This HTML is unescaped. Be careful!')), ('rich_text', RichTextBlock()), ], null=True, blank=True) core_technologies = RichTextField(blank=True) referrals = RichTextField(blank=True) preferred = RichTextField(blank=True) qualifications = RichTextField(blank=True) experience_we_need = RichTextField(blank=True) panels = [ MultiFieldPanel([ FieldPanel('title'), FieldPanel('background'), FieldPanel('responsibilities'), FieldPanel('skills'), FieldPanel('notes'), FieldPanel('location'), FieldPanel('core_technologies'), FieldPanel('qualifications'), FieldPanel('experience_we_need'), FieldPanel('preferred'), FieldPanel('referrals'), FieldPanel('benefits'), StreamFieldPanel('applying'), ]), ] class Meta: ordering = ['title'] def __str__(self): return '{self.title}'.format(self=self)
class PostStreamBlock(StreamBlock): """ Defines the ``StreamBlock`` used in the ``BlogPage`` model. This adds a dynamic behavior when writing the body of a new blog page. It includes: - h2 and h2 titles - a paragraph - an image that could be aligned on the left, on the right, in the center or with a full width - a quote with a proper attribution """ h2 = CharBlock(icon="title") h3 = CharBlock(icon="title") paragraph = RichTextBlock(icon="pilcrow") aligned_image = ImageBlock(label=_("Aligned image"), icon="image") pullquote = PullQuoteBlock(icon="openquote")
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 ThreeColumnBlock(StructBlock): block_heading = CharBlock(required=True) first_column_heading = CharBlock(required=True) first_column_text = RichTextBlock(required=True) first_column_color = ChoiceBlock(choices=COLORS, required=True) first_column_icon = ChoiceBlock(choices=ICONS, required=True) first_column_page = PageChooserBlock(required=False) second_column_heading = CharBlock(required=True) second_column_text = RichTextBlock(required=True) second_column_color = ChoiceBlock(choices=COLORS, required=True) second_column_icon = ChoiceBlock(choices=ICONS, required=True) second_column_page = PageChooserBlock(required=False) third_column_heading = CharBlock(required=True) third_column_text = RichTextBlock(required=True) third_column_color = ChoiceBlock(choices=COLORS, required=True) third_column_icon = ChoiceBlock(choices=ICONS, required=True) third_column_page = PageChooserBlock(required=False) class Meta: image = 'pages/images/streamfield_blocks/three_columns.jpg' template = 'pages/streamfield_blocks/three_columns.html'
class PressStreamBlock(StreamBlock): heading = CharBlock(icon="title", classname="title") subheading = CharBlock(icon="title", classname="title") text = RichTextBlock(icon="pilcrow", features=['bold', 'italic', 'ul', 'ol', 'link']) image = ImageChooserBlock(template='press/blocks/image.html') image_gallery = ListBlock(CaptionedImageBlock(), icon="image", label="Image Slideshow") #image_or_video_gallery = ListBlock(CarouselBlock(), icon="image", label="Image or Video Slideshow") video = EmbedBlock() project = PageChooserBlock(target_model='design.ProjectPage', template='design/blocks/related_project.html') pullquote = BlockQuoteBlock() document = DocumentChooserBlock(icon="doc-full-inverse")
class ContentPage(Page): body = StreamField([ ('text', RichTextBlock()), ('author', ModelChooserBlock(Author)), ('book', ModelChooserBlock(Book)), ]) favourite_book = models.ForeignKey(Book, blank=True, null=True, on_delete=models.SET_NULL, related_name='+') content_panels = Page.content_panels + [ StreamFieldPanel('body'), ModelChooserPanel('favourite_book'), ]
class BodyStreamBlock(StreamBlock): """ Defines a ``StreamBlock`` with a dynamic behavior when writing the body of new pages. It includes: - h2 and h3 titles - a paragraph - an image that could be aligned on the left, on the right, in the center or with a full width - a quote with attributions - an embedded iframe for videos """ h2 = CharBlock(icon="title") h3 = CharBlock(icon="title") paragraph = RichTextBlock(icon="pilcrow") image = ImageBlock(label=_("Aligned image"), icon="image") video = VideoBlock(label=_("Embedded video"), icon="media") pullquote = PullQuoteBlock(label=_("Quote"), icon="openquote")
class BlogBodyBlock(StreamBlock): heading = CharBlock(classname="full title", icon='title', template='blog/blocks/heading.html') quote = QuoteBlock() paragraph = RichTextBlock(icon='doc-full', label="Rich Text") image = ImageChooserBlock(icon='image') embed = EmbedBlock(icon='media') caption = CaptionBlock() raw_html = RawHTMLBlock( icon='code', label="Raw HTML", help_text=format_html( '<ul class="messages"><li class="error">Please mind that ' 'using raw HTML can break site rendering and/or compromise ' 'site security.</li></ul>'), )
class FormFieldsBlock(StreamBlock): char = CharFieldBlock(group=_('Fields')) text = TextFieldBlock(group=_('Fields')) number = NumberFieldBlock(group=_('Fields')) checkbox = CheckboxFieldBlock(group=_('Fields')) radios = RadioButtonsFieldBlock(group=_('Fields')) dropdown = DropdownFieldBlock(group=_('Fields')) checkboxes = CheckboxesFieldBlock(group=_('Fields')) date = DateFieldBlock(group=_('Fields')) time = TimeFieldBlock(group=_('Fields')) datetime = DateTimeFieldBlock(group=_('Fields')) image = ImageFieldBlock(group=_('Fields')) file = FileFieldBlock(group=_('Fields')) text_markup = RichTextBlock(group=_('Other')) class Meta: label = _('Form fields')
class HeadingWithTextBlock(StructBlock): block_heading = CharBlock(required=True) style = ChoiceBlock(choices=[('white', 'White background'), ('community', 'Community background')], required=True) items = ListBlock( StructBlock([ ('heading', CharBlock(required=True)), ('text', RichTextBlock(required=True)), ])) read_more_button = ReadMoreButtonBlock(required=False) class Meta: image = 'pages/images/streamfield_blocks/heading_with_text.jpg' template = 'pages/streamfield_blocks/heading_with_text.html'
class PostPage(Page): date = models.DateField(auto_now=True) header_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+') body = StreamField([ ('post_heading', CharBlock(max_length=40)), ('section_heading', CharBlock(max_length=40)), ('inline_image', ImageChooserBlock()), ('panorama_image', ImageChooserBlock()), ('paragraph', RichTextBlock()), ('code', CodeBlock()), ('video', EmbedBlock()), ('left_aligned_image', LeftAlignedImage()), ('right_aligned_image', RightAlignedImage()), ('two_column_code_block', TwoColumnCodeBlock()), ('left_aligned_code_block', LeftAlignedCodeBlock()), ('right_aligned_code_block', RightAlignedCodeBlock()), ]) categories = ParentalManyToManyField('blog.PostPageCategory', blank=True) tags = ClusterTaggableManager(through='blog.PostPageTag', blank=True) content_panels = Page.content_panels + [ ImageChooserPanel('header_image'), StreamFieldPanel('body'), FieldPanel('categories', widget=forms.CheckboxSelectMultiple), FieldPanel('tags'), ] search_fields = Page.search_fields + [ index.SearchField('body'), ] def get_context(self, request, *args, **kwargs): context = super(PostPage, self).get_context(request, *args, **kwargs) context['home_page'] = self.get_parent().specific context['post'] = self return context
class StreamPage(Page): class Meta: verbose_name = "Content Stream Page" content = StreamField([ ('heading', CharBlock(classname="full title", icon="title")), ('paragraph', RichTextBlock(icon="pilcrow")), ('image', ImageChooserBlock(icon="image")), ('embed', EmbedBlock(icon="media")), ], null=True, blank=True) content.help_text = "A page made up of blocks of text, images, video, etc." content_panels = Page.content_panels + [StreamFieldPanel('content')] promote_panels = [ MultiFieldPanel(Page.promote_panels, "Common page configuration") ]
class TextBlock(StructBlock): variant = ChoiceBlock( choices=VARIANT_CHOICES ) value = RichTextBlock() def __init__(self, **kwargs): super().__init__(**kwargs) # delete labels as we don't want them to appear in the admin for child_block in self.child_blocks.values(): child_block.label = None # only markdown supported atm so hiding the choices dropdown self.child_blocks['variant'].field.widget = forms.HiddenInput() class Meta: default = { 'variant': VARIANT_MARKDOWN }
class BlogIndexPage(MenuPage): body = StreamField([ ('heading', HeadingBlock()), ('richtext', RichTextBlock()), ('image', ImageBlock()), ('blog_posts', LatestBlogPostsBlock()), ]) content_panels = MenuPage.content_panels + [ StreamFieldPanel('body'), ] api_fields = [ 'body', ] parent_page_types = ['reactail.HomePage', 'reactail.ContentPage'] subpage_types = ['reactail.BlogPost'] class Meta: verbose_name = _('Blog index')
class ContentPage(MenuPage): body = StreamField([ ('heading', HeadingBlock()), ('richtext', RichTextBlock()), ('image', ImageBlock()), ]) content_panels = MenuPage.content_panels + [ StreamFieldPanel('body'), ] api_fields = [ 'body', ] parent_page_types = ['reactail.HomePage', 'reactail.ContentPage'] subpage_types = ['reactail.ContentPage', 'reactail.BlogIndexPage'] class Meta: verbose_name = _('Content page') verbose_name_plural = _('Content pages')
class SimplifiedBlock(StreamBlock): paragraph = RichTextBlock(icon="pilcrow", template="blocks/paragraph.html") header = CharBlock(classname="title", icon="fa-header", template="blocks/h3.html") image = StructBlock([('image', ImageChooserBlock()), ('caption', CharBlock(blank=True, required=False)), ('style', ChoiceBlock(choices=[('', 'Select an image size'), ('full', 'Full-width'), ('half', 'Half-width')], required=False))], icon="image", template="blocks/image.html") blockquote = StructBlock([ ('text', TextBlock()), ('attribute_name', CharBlock(blank=True, required=False, label='e.g. Guy Picciotto')), ('attribute_group', CharBlock(blank=True, required=False, label='e.g. Fugazi')), ], icon="openquote", template="blocks/blockquote.html")
class StandardBlock(StreamBlock): paragraph = RichTextBlock(icon="pilcrow", template="blocks/paragraph.html") header = StructBlock([ ('header_text', CharBlock(blank=True, required=False, label='Header')), ('size', ChoiceBlock(choices=[('', 'Select a header size'), ('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')], blank=True, required=False)) ], classname="title", icon="fa-header", template="blocks/header.html") image = StructBlock([('image', ImageChooserBlock()), ('caption', CharBlock(blank=True, required=False)), ('style', ChoiceBlock(choices=[('', 'Select an image size'), ('fit', 'Contained width'), ('full', 'Full-width'), ('square', 'Square')], required=False))], icon="image", template="blocks/image.html") blockquote = StructBlock([ ('text', TextBlock()), ('attribute_name', CharBlock(blank=True, required=False, label='e.g. Guy Picciotto')), ('attribute_group', CharBlock(blank=True, required=False, label='e.g. Fugazi')), ], icon="openquote", template="blocks/blockquote.html") embed = EmbedBlock( help_text= 'Insert an embed URL e.g https://www.youtube.com/embed/SGJFWirQ3ks', icon="embed", template="blocks/embed.html")