5 Tips to Streamline Your Wagtail CMS Development

Hi! I’m Patryk. I’m a Python Backend developer at Profil Software. In my work, I’ve had a chance to use Wagtail to build a few applications. It’s a free and open-source content management system written in Python that is based on Django. That makes it easy and speeds up development. In this article, I would like to share a few tips with you that came out of my work. I hope that it will help you build Wagtail applications more efficiently.

Use explorer feature

Before creating any application, you should consider what your website would look like when it comes to the hierarchy of pages. Wagtail offers support for organizing your pages into folders and thus creating paths to them. You should avoid flat structure as it complicates using the admin panel because over time there can be a lot of pages and navigating between them can become problematic. Also, a well-designed page structure helps you to configure SEO for your pages.

You can force the user to follow your hierarchy by using parent_page_types and subpage_types properties in your page model. For a simple blog, I would create a hierarchy like this:

We have a root. Each category has its page and generates the proper path. Each article belongs to a category.

Here is the code:

class BlogPage(Page):
subpage_types = ["blog.BlogCategoryPage"]
parent_page_types = ["wagtailcore.page"] # root
max_count = 1
# Rest of the code...class BlogCategoryPage(Page):
subpage_types = ["blog.PostPage"]
parent_page_types = ["blog.BlogPage"]
# Rest of the code...class PostPage(Page):
subpage_types = []
parent_page_types = ["blog.BlogCategoryPage"]
# Rest of the code…

Enjoying this article? Need help? Talk to us!

Receive a free consultation on your software project

For images consider using `wagtail.images.models.imageField`

First of all, it has a wagtail panel that looks user-friendly. Another important feature is that you can add custom fields, for example, caption. You can find out here how you can do it. And last but not least, the model allows you to easily convert and scale images by using get_rendition method. For example, image.get_rendition(“fill-800x600|format-webp|webpquality-95”) produces a webp image with size 800x600 and quality 95 and saves it when trying to use it again.

Example code

class CustomImage(AbstractImage):
alt = models.CharField(max_length=512, null=True)
caption = models.CharField(max_length=512, null=True, blank=True)
admin_form_fields = Image.admin_form_fields + ("alt", "caption")
def get_optimized_sizes(self):
large_width, large_height = ...
big_width, big_height = ...
medium_width, medium_height = ...
small_width, small_height = ...
tiny_width, tiny_height = ...
return {
"thumbnail_large": self._get_url(
self.get_rendition(
f"fill-{large_width}x{large_height}|format-webp|webpquality-95"
)
),
"thumbnail_big": self._get_url(
self.get_rendition(
f"fill-{big_width}x{big_height}|format-webp|webpquality-95"
)
),
"thumbnail_medium": self._get_url(
self.get_rendition(
f"fill-{medium_width}x{medium_height}|format-webp|webpquality-95"
)
),
"thumbnail_small": self._get_url(
self.get_rendition(
f"fill-{small_width}x{small_height}|format-webp|webpquality-95"
)
),
"thumbnail_tiny": self._get_url(
self.get_rendition(
f"fill-{tiny_width}x{tiny_height}|format-webp|webpquality-95"
)
),
"alt": self.alt,
"id": self.id,
}

And here is how it looks like

StreamField for complex structure

When I was creating a blog application I had to create a post model with an extended content field. As you know, the field can contain anything, starting from GitHub gist, special styled links, and ending with a gallery. Unfortunately, the Wagtail rich text editor wasn’t sufficient. I found that there is a StreamField. After a few hours of studying, I managed to create a very nice-looking widget that the client could use and add all these fancy things. You just simply create “blocks” with desired fields and then include them in the StreamField. With this field, you can create very complex widgets. More about it here.

Example StreamField block

class AdBlock(wagtail_blocks.StructBlock):
title = wagtail_blocks.CharBlock(max_length=128)
sub_title = wagtail_blocks.RichTextBlock()
product = wagtail_blocks.PageChooserBlock()

And the PostPage

class PostPage(Page):
content = StreamField(
[
("text", wagtail_blocks.RichTextBlock()),
("gallery", wagtail_blocks.ListBlock(ImageChooserBlock())),
("heading", wagtail_blocks.CharBlock(form_classname="full title")),
("image", ImageChooserBlock()),
("Ad", AdBlock()),
]
)
# Rest of the code...

Final result:

And the AdBlock

Interested in working for our software development company in Poland?

Check out our current job offers now!

When your page is too big, divide it into tabs

I created a home page. Initially, there were only a few things with content. Over time, It was growing and growing, and adding new content became problematic because finding a proper place to put new content took years. I had to scroll over all these inputs and search for the one I am looking for. I found that wagtail shares a feature that allows you to divide a page into tabs! After moving stuff around a little, it looked much better and more intuitive for users. Learn here how to do it.

Example code for dividing blog into tabs:

class BlogPage(Page):
# Fields defined here

content_panels = Page.content_panels + [
MultiFieldPanel(
[
FieldPanel("subtitle"),
ImageChooserPanel("top_image"),
],
"Top",
),
]

newsletter_panel = [
MultiFieldPanel(
[
FieldPanel("newsletter_apply_title"),
FieldPanel("newsletter_apply_subtitle"),
FieldPanel("newsletter_apply_button_name"),
FieldPanel("newsletter_apply_url"),
FieldPanel("newsletter_apply_icon"),
FieldPanel("newsletter_apply_icon_alt"),
],
"apply",
),
]

edit_handler = TabbedInterface(
[
ObjectList(content_panels, heading="Content"),
ObjectList(newsletter_panel, heading="Newsletter"),
ObjectList(Page.promote_panels, heading="Promotion"),
ObjectList(Page.settings_panels, heading="Settings"),
]
)

Final result:

Extra tip

Over the years, the Wagtail community was growing and thus many libraries were made that are extending the wagtail features. Founding the proper one can be challenging, and you don’t know what is available. I found the Github page where you can find most of them. Moreover, there are presentations, videos, podcasts, and many more materials.

That’s all the tips I wanted to share with you. I hope that you can use some of them to build better wagtail applications.

--

--