Steps

Snippets are a way for you to use code/data over and over again.

You can register a django model as a snippet and use that as a re-usable template.

first we define a new model in blogs/models.py:

class BlogAuthor(models.Model):
    """Blog author for snippets."""

    name = models.CharField(max_length=100)
    website = models.URLField(blank=True, null=True)
    image = models.ForeignKey(
        'wagtailimages.Image',
        on_delete=models.SET_NULL,
        null=True,
        blank=False,
        related_name="+"
    )

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("name"),
                FieldPanel("image"),
            ],
            heading="Name and Image",
        ),
        MultiFieldPanel(
            [
                FieldPanel("website")
            ],
            heading="Links"
        )
    ]

    def __str__(self):
        """String repr of this class."""
        return self.name

    class Meta:
        verbose_name = "Blog Author"
        verbose_name_plural = "Blog Authors"

Usually with this model you’d register it into the django admin panel and be able to edit it, but we want to use it in the wagtail admin panel, so we’re going to have to register it as a snippet.

from wagtail.snippets.models import register_snippet

register_snippet(BlogAuthor)

Untitled

You can now use thie page to add, edit, or delete authors!

The next step is to link an author with a post so we can show them together on our pages!

An orderable is much like a streamfield but the data it holds is one type, like being able to select multiple blog authors and put them in a certain order.

class BlogAuthotsOrderable(Orderable):
    """This allows us to select on or more blog authors"""

    page = ParentalKey("BlogApp.BlogDetailPage", related_name="blog_authors")
    author = models.ForeignKey(
        "BlogApp.BlogAuthor",
        on_delete=models.CASCADE,
    )

    panels = [
        FieldPanel("author"),
    ]

Now add it to content_panels of BlogDetailPage!

class BlogDetailPage(Page):
    """Blog detail page"""

    template = "blog/blog_detail_page.html"

    custom_title = models.CharField(
        max_length=100,
        blank=False,
        null=False,
        help_text='overwrite default title'
    )
    blog_image = models.ForeignKey(
        "wagtailimages.Image",
        blank=False,
        null=True,
        related_name="+",
        on_delete=models.SET_NULL
    )

    content = StreamField(
        [
            ("title_and_text", blocks.TitleAndTextBlock(classname="text_and_title")),
            ("full_rich_text", blocks.RichTextBlock(classname="full_rich_text")),
            ("my_rich_text", blocks.MyRichTextBlock(classname="my_rich_text")),
            ("cards", blocks.CardBlock()),
            ("cta", blocks.CTABlock()),
        ],
        null=True,
        blank=True,
        use_json_field=True
    )
    content_panels = Page.content_panels + [
        FieldPanel("custom_title"),
        FieldPanel("blog_image"),
        MultiFieldPanel(
            [
                InlinePanel("blog_authors", label="Author", min_num=1, max_num=4)
            ], heading="Author(s)"
        ),
        FieldPanel("content")
    ]

Untitled

Now it shows up in the admin page, but we still need to add it to our template/

Untitled