class BootstrapCol(blocks.StructBlock): width = blocks.IntegerBlock(max_value=12, min_value=0, help_text='0 = auto', default=0) alignment = blocks.ChoiceBlock(choices=[ ('center', 'Center'), ('right', 'Right'), ('left', 'Left'), ], default='center') vertical_center = blocks.BooleanBlock(default=False, blank=True, required=False) body = blocks.StreamBlock([ (_('Rich_Text'), blocks.RichTextBlock()), (_('Text'), blocks.TextBlock()), (_('Image'), ImageChooserBlock(icon="image")), (_('Embedded_Video'), EmbedBlock(icon="media")), (_('HTML'), blocks.RawHTMLBlock()), (_('Quote'), blocks.BlockQuoteBlock()), (_('Optin'), OptinChooserBlock('optin.Optin')), (_('Code'), CodeBlock(label='Code Editor')), (_('Aligned_Image'), AlignedImageBlock()), ], blank=True, null=True, required=False) class Meta: icon = 'grip' label = 'Bootstrap Col' template = 'blog/blocks/bootstrap_col.html'
class EventPage(CustomPage): ''' Event page content ''' date = models.DateField('Fecha publicación') is_meetup = models.BooleanField('Evento de meetup', default=False) event_url = models.URLField('URL', max_length=250, blank=True, null=True) description = models.TextField('Descripción', blank=True) image = models.ImageField('Imagen principal', blank=True, null=True) meetup_image_url = models.URLField('Meetup image url', blank=True, null=True) editor_features = [ 'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'code', 'ol', 'ul', 'hr', 'document-link', 'image', 'embed', 'strikethrough', 'blockquote' ] body = StreamField([ ('heading', blocks.CharBlock(classname='full title')), ('paragraph', blocks.RichTextBlock(features=editor_features)), ('code', CodeBlock(label='Code')), ('image', ImageChooserBlock()), ], blank=True, null=True) content_panels = Page.content_panels + [ FieldPanel('description', classname='full'), FieldPanel('date'), FieldPanel('image'), StreamFieldPanel('body') ] subpage_types = []
class ColumnBlock(blocks.StructBlock): """ Renders a row of md-6 columns. """ # todo coudn't find a way to avoid circular name errors, so copy pasted here local_blocks = ( ("paragraph", ParagraphBlock()), ("image", ImageBlock()), ("video", VideoBlock(column="2")), ("download", DownloadBlock()), ("quote", QuoteBlock()), ("image_gallery", ImageGalleryBlock()), ("table", TableBlock()), ("map", GoogleMapBlock()), ("code", CodeBlock()), ("card_group", CardGroupBlock()), # todo This looks naff ) class Meta: template = "streams/two_column_block.html" icon = "fa-columns" label = "2 Column block" help_text = "The first block will go on the left." def __init__(self, local_blocks=local_blocks): local_blocks = (( "content", blocks.StreamBlock(local_blocks, label="Select two columns.", min_num=2, max_num=2), ), ) super().__init__(local_blocks, )
class FlexPage(Page): """Flexible page class.""" template = "flex/flex_page.html" content = StreamField( [ ("full_richtext", blocks.RichtextBlock(classname="richtext")), ("features_and_tools", blocks.FeaturesAndToolsBlock(classname="featuresandtools")), ("codeblock", CodeBlock(label='Code Block', default_language='python')) ], null=True, blank=True ) subtitle = models.CharField(max_length=100, null=True, blank=True) content_panels = Page.content_panels + [ FieldPanel("subtitle"), StreamFieldPanel("content"), ] class Meta: verbose_name = "Flex Page" verbose_name_plural = "Flex Pages"
class ArticlePage(TranslatablePage): intro = RichTextField(blank=True) image = models.ForeignKey( "wagtailimages.Image", blank=True, null=True, on_delete=models.SET_NULL, related_name="+", verbose_name=_("Image"), ) themes = ParentalManyToManyField(Theme, blank=True, related_name="articlepages", verbose_name=_("Themes")) featured = models.BooleanField(default=False) body = StreamField([ ( "paragraph", blocks.RichTextBlock(features=[ "h1", "h2", "h3", "h4", "h5", "bold", "italic", "ol", "ul", "hr", "link", "image", "code", "blockquote", ]), ), ("code", CodeBlock(label=_("Code"))), ("image", InlineImageBlock()), ("video", InlineVideoBlock()), ]) def themepages(self): return ThemePage.objects.filter(theme__in=self.themes.all(), language=self.language) def get_absolute_url(self): return self.get_url() def serve(self, request, *args, **kwargs): response = super().serve(request, "cms/article_page.html") response.context_data["login_form"] = LoginForm() return response content_panels = TranslatablePage.content_panels + [ FieldPanel("intro"), FieldPanel("themes", widget=forms.CheckboxSelectMultiple), FieldPanel("featured"), ImageChooserPanel("image"), StreamFieldPanel("body"), InlinePanel("customcomments", label=_("Comments")), ]
class ContentStreamBlock(StreamBlock): heading = TextBlock() paragraph = TextBlock() code = CodeBlock(label='Code') class Meta: icon = 'code'
class PostPage(CustomPage): ''' Post content ''' date = models.DateField("Fecha publicación") description = models.CharField("Descripción", max_length=255, blank=True) image = models.ImageField("Imagen principal", blank=True, null=True) editor_features = [ 'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'code', 'ol', 'ul', 'hr', 'document-link', 'image', 'embed', 'strikethrough', 'blockquote' ] body = StreamField([ ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock(features=editor_features)), ('code', CodeBlock(label='Code')), ('image', ImageChooserBlock()), ], blank=True, null=True) content_panels = Page.content_panels + [ FieldPanel('description', classname="full"), FieldPanel('date'), FieldPanel('image'), StreamFieldPanel('body') ] subpage_types = []
class ParallaxHeaderBlock(blocks.StructBlock): background = ImageChooserBlock(blank=True) title = blocks.CharBlock(blank=True) body = blocks.StreamBlock( [ (_('Rich_Text'), blocks.RichTextBlock()), (_('Text'), blocks.TextBlock()), (_('Image'), ImageChooserBlock(icon="image")), # (_('Image(aligned)'), AlignedImageBlock()), (_('Embedded_Video'), EmbedBlock(icon="media")), (_('HTML'), blocks.RawHTMLBlock()), (_('Quote'), blocks.BlockQuoteBlock()), (_('Optin'), OptinChooserBlock('optin.Optin')), (_('Code'), CodeBlock(label='Code Editor')), (_('Bootstrap_Row'), BootstrapRow()), (_('Bootstrap_Col'), BootstrapCol()), (_('Aligned_Image'), AlignedImageBlock()), ], blank=True, null=True, required=False) class Meta: icon = 'form' label = 'Parallax Header' template = 'blog/blocks/parallax_header.html'
class BlogPage(Page): date = models.DateField("Post date") tags = ClusterTaggableManager(through=BlogPageTag, blank=True) categories = ParentalManyToManyField('blog.BlogCategory', blank=True) body = StreamField([ ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('image', ImageChooserBlock()), ('code', CodeBlock(icon='code')), ]) content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('date'), FieldPanel('tags'), FieldPanel('categories', widget=forms.CheckboxSelectMultiple), ], heading="Blog information"), InlinePanel('gallery_images', label="Gallery images"), StreamFieldPanel('body'), ] search_fields = Page.search_fields + [ index.SearchField('body'), ] def main_image(self): gallery_item = self.gallery_images.first() if gallery_item: return gallery_item.image else: return None
class CraftPost(Page): author = models.CharField(max_length=255, blank=True, null=True) date = models.DateField("Post date") featured = models.BooleanField(default=False) body = StreamField([ ('content', blocks.RichTextBlock()), ('quote', blocks.BlockQuoteBlock()), ('image', ImageChooserBlock(template="frontend/craftbox/blocks/image.html")), ('embed', EmbedBlock()), ('code', CodeBlock()) ]) cover_image = models.ForeignKey( 'wagtailimages.Image', help_text="An optional image to represent the page", null=True, blank=True, on_delete=models.SET_NULL, related_name='+' ) excerpt = StreamField([ ('qoute', blocks.BlockQuoteBlock())] ) tags = ClusterTaggableManager(through=CraftPostTag, blank=True) post_category = models.ForeignKey( CraftboxCategory, null=True, blank=True, on_delete=models.SET_NULL, related_name='+' ) search_fields = Page.search_fields + [ index.SearchField('featured'), index.SearchField('body'), index.SearchField('tags'), index.SearchField('post_category', boost=4) ] content_panels = Page.content_panels + [ FieldPanel('author'), StreamFieldPanel('body'), ] promote_panels = Page.promote_panels + [ FieldPanel('date'), FieldPanel('featured'), ImageChooserPanel('cover_image'), StreamFieldPanel('excerpt'), FieldPanel('tags'), SnippetChooserPanel('post_category'), ] parent_page_types = ['craftbox.CraftHome'] subpage_types = [] def get_template(request, *args, **kwargs): return "frontend/craftbox/post.html" class Meta: verbose_name = "craft post page"
class ContentStreamBlock(StreamBlock): h2 = CharBlock(icon="title", classname="title") h3 = CharBlock(icon="title", classname="title") h4 = CharBlock(icon="title", classname="title") paragraph = RichTextBlock(required=False) code = CodeBlock(label='Code', required=False) embeds = EmbedBlock(required=False) markdown = MarkDownBlock(required=False)
class CodingBlock(blocks.StructBlock): code = CodeBlock(form_classname="post_code", required=False) language = blocks.ChoiceBlock(default="python") text = blocks.TextBlock() class Meta: icon = "code" template = "blog/streams/code_block.html"
class ColumnBlock(blocks.StreamBlock): heading = blocks.CharBlock(classname="full title") paragraph = blocks.RichTextBlock() code = CodeBlock() image = ImageChooserBlock() class Meta: template = 'frontend/craftbox/blocks/column.html'
class MultiSectionBlock(blocks.StreamBlock): text_block = blocks.RichTextBlock() quote_block = blocks.BlockQuoteBlock() code_block = CodeBlock() class Meta: icon = "placeholder" label = "Multi Section"
class PostPage(Page): body = MarkdownField() date = models.DateTimeField(verbose_name="Post date", default=datetime.today) body_stream = StreamField( [('heading', blocks.CharBlock(classname='full title')), ('paragraph', blocks.RichTextBlock()), ('image', ImageChooserBlock()), ('code', CodeBlock())], blank=True) excerpt = MarkdownField( verbose_name='excerpt', blank=True, ) header_image = models.ForeignKey( 'wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+', ) categories = ParentalManyToManyField('blog.BlogCategory', blank=True) tags = ClusterTaggableManager(through='blog.BlogPageTag', blank=True) content_panels = Page.content_panels + [ ImageChooserPanel('header_image'), MarkdownPanel("body"), MarkdownPanel("excerpt"), StreamFieldPanel("body_stream"), FieldPanel('categories', widget=forms.CheckboxSelectMultiple), FieldPanel('tags'), ] settings_panels = Page.settings_panels + [ FieldPanel('date'), ] @property def blog_page(self): return self.get_parent().specific ''' @property def category_page(self): return self.get_parent().specific ''' def get_context(self, request, *args, **kwargs): context = super(PostPage, self).get_context(request, *args, **kwargs) context['blog_page'] = self.blog_page #context['category_page'] = self.category_page context['post'] = self return context
class CodeRichBlock(blocks.StructBlock): code_url = blocks.URLBlock(label="External URL", required=False) code = CodeBlock(label='Source Code', language='WAGTAIL_CODE_BLOCK_LANGUAGES', required=False) align = blocks.ChoiceBlock(choices=CHOICES_ALIGN, required=True, default=('left', 'Left')) class Meta: icon = 'code' value_class = LinkStructValue
class TutorialPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) promo_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+') body = StreamField([ ('paragraph', blocks.RichTextBlock(features=[ 'h2', 'h3', 'h4', 'h5', 'bold', 'italic', 'ol', 'ul', 'hr', 'link', 'document-link', 'code', 'superscript', 'subscript', 'strikethrough', 'blockquote' ])), ('image', ImageChooserBlock()), ('code', CodeBlock(label='Code', default_language='python')), ('video', VideoBlock()), ]) tags = ClusterTaggableManager(through=TutorialPageTag, blank=True) search_fields = Page.search_fields + [ index.SearchField('intro'), index.SearchField('body'), ] content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('date'), FieldPanel('intro'), ImageChooserPanel('promo_image'), FieldPanel('tags'), FieldPanel('owner') ], heading="Tutorial Info"), StreamFieldPanel('body'), ] def get_context(self, request): context = super().get_context(request) courses = Course.objects.filter( tags__name__in=self.tags.all()).distinct() context['courses'] = courses return context def get_read_time(self): ''' Returns the read time of the Content body ''' string = str(self.body) result = readtime.of_html(string) return result
class BlogPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) body = StreamField([ ('first_paragraph', blocks.CharBlock()), ('pullquotes', blocks.CharBlock()), ('blockquotes', blocks.StructBlock([ ('quote', blocks.CharBlock()), ('cite', blocks.CharBlock()), ('cite_link', blocks.URLBlock(required=False)), ], template='blocks/bquote.html')), ('image', ImageChooserBlock()), ('list', blocks.ListBlock(blocks.CharBlock())), ('paragraph', blocks.RichTextBlock()), ('code', CodeBlock()), ('raw_html', blocks.RawHTMLBlock()), ]) tags = ClusterTaggableManager(through=BlogPageTag, blank=True) categories = ParentalManyToManyField('realblog.BlogCategory', blank=True) def main_image(self): gallery_item = self.gallery_images.first() if gallery_item: return gallery_item.image else: return None search_fields = Page.search_fields + [ index.SearchField('intro'), index.SearchField('body'), ] content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('date'), FieldPanel('tags'), FieldPanel('categories', widget=forms.CheckboxSelectMultiple), ], heading="Blog information"), FieldPanel('intro'), StreamFieldPanel('body'), InlinePanel('gallery_images', label="Gallery images"), ] parent_page_types = [ BlogIndexPage, ]
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") code_block = CodeBlock(label='Code block') 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")
def single_column_blocks(): """Function to return all block types suitable for full width""" single_column_blocks = [ ("column_block", ColumnBlock()), ("paragraph", ParagraphBlock()), ("image", ImageBlock()), ("video", VideoBlock(column="1")), ("download", DownloadBlock()), ("quote", QuoteBlock()), ("image_gallery", ImageGalleryBlock()), ("table", TableBlock()), ("map", GoogleMapBlock()), ("code", CodeBlock()), ("card_group", CardGroupBlock()), ] return single_column_blocks
class Post(Page): date = models.DateField("Post Date") intro = models.CharField(max_length=255) body = StreamField([ ("heading", blocks.CharBlock(classname="full title")), ("paragraph", blocks.RichTextBlock(features=[ "h1", "h2", "h3", "h4", "h5", "h6", "bold", "italic", "ol", "ul", "hr", "link", "documen", "image", "embed", "code", "blockquote", ])), ("image", ImageChooserBlock(classname="img-fluid")), ("code", CodeBlock()), ]) tags = ClusterTaggableManager(through="Tag", blank=True) search_fields = Page.search_fields + [ index.SearchField("intro"), index.SearchField("body"), ] content_panels = Page.content_panels + [ MultiFieldPanel([FieldPanel("date"), FieldPanel("tags")]), FieldPanel("intro", classname="full"), StreamFieldPanel("body"), ] def get_tags(self): return TaggitTag.objects.filter(post=self).order_by("name")
class BlogPage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250) head_image = models.ForeignKey(Image, null=True, blank=True, on_delete=models.SET_NULL, related_name='+') body = StreamField([ ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), # ('recipe', SnippetChooserBlock(Recipe)), # оставил для примера ('code', CodeBlock(label='code')), ('markdown', MarkdownBlock()), ('image', ImageChooserBlock()), ]) search_fields = Page.search_fields + [ index.SearchField('intro'), index.SearchField('body') ] content_panels = Page.content_panels + [ FieldPanel('date'), FieldPanel('intro'), ImageChooserPanel('head_image'), StreamFieldPanel('body'), ] promote_panels = Page.promote_panels + [ FieldPanel('tags'), ] tags = ClusterTaggableManager(through=BlogPageTag, blank=True) views = models.IntegerField('Просмотры', default=0) votes = GenericRelation(Vote, related_query_name='articles') comments = GenericRelation(Comment, related_query_name='articles') def save(self, *args, **kwargs): if not self.id: if self.slug: self.slug = slugify(self.slug) else: self.slug = slugify(self.title)[:250] super().save(*args, **kwargs)
class ArticlePage(Page): date = models.DateField("Post date") intro = models.CharField(max_length=250, blank=True, null=True) body = StreamField( [ ("paragraph", blocks.RichTextBlock()), ("image", ImageChooserBlock()), ("code", CodeBlock(label="Code")), ], null=True, blank=True, ) author = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, editable=True, on_delete=models.SET_NULL, related_name="authored_pages", help_text="Choose from the list or create a new user", ) search_fields = Page.search_fields + [ index.SearchField("intro"), index.SearchField("body"), ] content_panels = Page.content_panels + [ FieldPanel("date"), FieldPanel("intro"), StreamFieldPanel("body"), FieldPanel("author"), ] parent_page_types = ["article.ArticleIndexPage"] def get_context(self, request, *args, **kwargs): context = super(ArticlePage, self).get_context(request, *args, **kwargs) context["siblings"] = (ArticlePage.objects.live().sibling_of( self, inclusive=False).order_by("title")) return context
class ArticlePage(TranslatablePage): intro = RichTextField(blank=True) image = models.ForeignKey('wagtailimages.Image', blank=True, null=True, on_delete=models.SET_NULL, related_name='+', verbose_name=_("Image")) themes = ParentalManyToManyField(Theme, blank=True, related_name='articlepages', verbose_name=_("Themes")) featured = models.BooleanField(default=False) body = StreamField([ ('paragraph', blocks.RichTextBlock(features=[ 'h1', 'h2', 'h3', 'h4', 'h5', 'bold', 'italic', 'ol', 'ul', 'hr', 'link', 'image', 'code', 'blockquote' ])), ('code', CodeBlock(label=_("Code"))), ('image', InlineImageBlock()), ('video', InlineVideoBlock()), ]) def themepages(self): return ThemePage.objects.filter(theme__in=self.themes.all(), language=self.language) def get_absolute_url(self): return self.get_url() def serve(self, request, *args, **kwargs): response = super().serve(request, 'cms/article_page.html') response.context_data['login_form'] = LoginForm() return response content_panels = TranslatablePage.content_panels + [ FieldPanel('intro'), FieldPanel('themes', widget=forms.CheckboxSelectMultiple), FieldPanel('featured'), ImageChooserPanel('image'), StreamFieldPanel('body'), InlinePanel('customcomments', label=_("Comments")), ]
class BlogPost(MetadataPageMixin, Page): date = models.DateField(default=now) body = StreamField([ ('heading', blocks.CharBlock(template="blog/block/heading.html")), ('paragraph', blocks.RichTextBlock(template="blog/block/paragraph.html")), ('image', imageblocks.ImageChooserBlock(template="blog/block/image.html")), ('embed', EmbedBlock(template="blog/block/embed.html")), ('code', CodeBlock()), ]) content_panels = Page.content_panels + [ FieldPanel('date'), StreamFieldPanel('body'), ] def get_context(self, request, *args, **kwargs): context = super(BlogPost, self).get_context(request, *args, **kwargs) parent = self.get_parent() context['parent'] = parent return context
class ConstructionBlock(blocks.StreamBlock): heading = HeadingBlock(required=False, icon='title') richtext = blocks.RichTextBlock(icon='pilcrow', label='Rich Text') paragraph = blocks.TextBlock(icon='pilcrow',template='blog/blocks/text_block.html', label='Simple Text') blockquote = blocks.BlockQuoteBlock(icon='openquote') image = ImageChooserBlock(icon='image') video = EmbedBlock(icon='media') code = CodeBlock(icon='code') search = SearchBlock(icon='search') author = AuthorBlock(icon='user') document = DocumentChooserBlock(icon='doc-full') email = blocks.EmailBlock(icon='mail') linklist = blocks.ListBlock( QuickLinkBlock(), template='blog/blocks/linklist_block.html', icon='link') documentlist = blocks.ListBlock(DocumentChooserBlock(icon='doc-full')) class Meta: template = 'blog/blocks/construction_block.html' icon = 'placeholder' label = 'Construction Block'
class ContentStreamBlock(StreamBlock): """ Contains the elements we'll want to have in a Content Stream. """ heading = TextBlock( icon='title', template='wagtailcontentstream/blocks/heading.html', ) paragraph = RichTextBlock( icon='pilcrow', features=['bold', 'italic', 'link', 'ol', 'ul', 'monospace'], ) image = CaptionedImageBlock() document = DocumentChooserBlock() embed = EmbedBlock(icon='media') table = TableBlock(icon='table') code = CodeBlock(icon='code') class Meta: help_text = 'The main page body.'
class StoryBlock(blocks.StreamBlock): heading = blocks.CharBlock(classname="full title", icon='title') paragraph = blocks.RichTextBlock( features=[ 'bold', 'italic', 'ul', 'ol', 'hr', 'link', 'document-link' ], ) image = ImageBlock() quote = QuoteBlock() embed = EmbedBlock() call_to_action = SnippetChooserBlock( 'utils.CallToActionSnippet', template="blocks/call_to_action_block.html" ) document = DocumentBlock() code = CodeBlock() class Meta: template = "blocks/stream_block.html"
class GeneralPage(CustomPage): ''' Multiuse page for general content ''' description = models.CharField("Descripción", max_length=255, blank=True) image = models.ImageField("Imagen principal", blank=True, null=True) body = StreamField([ ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('code', CodeBlock(label='Code')), ('image', ImageChooserBlock()), ], blank=True, null=True) content_panels = Page.content_panels + [ FieldPanel('description', classname="full"), FieldPanel('image'), StreamFieldPanel('body') ] subpage_types = []
class LandingPost(BasePost): Page = TranslatablePage body = StreamField([ ('heading', blocks.CharBlock(classname="full title")), ('paragraph', blocks.RichTextBlock()), ('code', CodeBlock(label='Code')), ('code_output', blocks.TextBlock()), ('image', ImageChooserBlock(icon="image")), ('table', TableBlock(icon="form", template='blog/blocks/table_template.html')), ('custom_html', blocks.TextBlock(icon='plus-inverse')), ], null=True, blank=True) content_panels = Page.content_panels + [ FieldPanel('categories', widget=forms.CheckboxSelectMultiple), StreamFieldPanel('body'), PageChooserPanel( 'related_page1', ['blog.PostPage', 'blog.LandingPage', 'blog.LandingPost']), PageChooserPanel( 'related_page2', ['blog.PostPage', 'blog.LandingPage', 'blog.LandingPost']), ] settings_panels = Page.settings_panels + [ FieldPanel('date'), ImageChooserPanel('thumbnail'), MultiFieldPanel([ FieldPanel('is_series'), FieldPanel('series_name'), FieldPanel('series_id') ], heading='SeriesSetting', classname="collapsible collapsed"), ] def get_context(self, request, *args, **kwargs): context = super().get_context(request, *args, **kwargs) return context