Wagtail is a powerful and flexible, open-source content management system (CMS) built upon Django, for developers and editors alike. One of its standout features is the StreamField, which gives developers the flexibility to create content in structured page form, that is, flexible structure page content. StreamFields can include different types of blocks, enabling content editors to build pages with diverse layouts and content types. In this article, we'll explore how to extend Wagtail by creating custom blocks and StreamField types that enrich the content editing experience.
Understanding StreamField
Before diving into creating custom blocks, let's briefly review what StreamFields are. A StreamField is a type of field in Wagtail that allows for an array of different content types, or blocks, to be added to a page. This makes it highly flexible and suitable for various types of content arrangements.
Each block can define its own unique structure and behavior, allowing for a tailored content entry experience. For example, you might have a rich text block, an image block, a video block, or even more complex blocks that incorporate data from multiple sources.
Key Concepts
Block: The basic unit of content that defines a specific type of data, like an image or textual content.
StreamField: A field that allows using multiple blocks in a structured way, enabling editors to create a rich mix of content on a single page.
Block Types: Each block has its type, usually defined as a Python class.
Setting Up Your Wagtail Environment
Before we begin creating our custom blocks, make sure you have Wagtail installed and set up in your Django project. If you haven't done this yet, you can create a new project and install Wagtail using the following commands:
# Install Wagtail
pip install wagtail
# Create a new Wagtail project
wagtail start myproject
cd myproject
Next, set up your database and run the initial migrations:
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Now you should have a basic Wagtail site running locally. You can log into the admin interface at http://localhost:8000/admin
.
Creating a Custom Block
Let's create a custom block that includes a text with a subtitle. This example will illustrate how to define a block, handle validation, and render it in a template.
Step 1: Define the Block
First, let's make a new Python file for our blocks. You can do this in your app in a new directory called blocks
, for example: home/
blocks.py
. Next, define your block with Django's form handling within your Wagtail app as follows:
# home/blocks.py
from wagtail.core import blocks
class TextSubtitleBlock(blocks.StructBlock):
title = blocks.CharBlock(required=True)
subtitle = blocks.CharBlock(required=True)
content = blocks.RichTextBlock()
class Meta:
``
template = 'blocks/text_subtitle_block.html'
icon = 'edit'
label = 'Text with Subtitle'
Above, we have declared a TextSubtitleBlock
which contains:
A title
field is of type CharBlock
. A subtitle
field also of type CharBlock
. A content
field to accept rich text.
The Meta
class defines the template to render the block and adds an icon and label to the Wagtail admin interface.
Step 2: Create the Template
You need to create a template that this block will use for rendering. So, create a new file at home/templates/blocks/text_subtitle_block.html
:
<div class="text-subtitle-block">
<h2>{{ self.title }}</h2>
<h3>{{ self.subtitle }}</h3>
<div>{{ self.content|safe }}</div>
</div>
This template creates a title, subtitle, and a content with the rich text from the fields of a block.
Step 3: Register your Block to a StreamField in Page Model
The next thing is to make your custom block registered for a StreamField in your Wagtail page model. Open the file for your page model, e.g., home/
models.py
, and append your custom block to a StreamField.
# home/models.py
from wagtail.core.models import Page
from wagtail.admin.edit_handlers import StreamFieldPanel
from wagtail.core.fields import StreamField
from.blocks import TextSubtitleBlock
class HomePage(Page):
body = StreamField([ ('text_subtitle', TextSubtitleBlock()), # You could add more blocks here ], use_json_field=True)
content_panels = Page.content_panels + [ StreamFieldPanel('body'), ]
### Step 4: Migrate Your Changes
Since we have changed the models, be sure to run migrations to apply changes to the database:
```bash
python manage.py makemigrations
python manage.py migrate
Step 5: Add to Admin
Log in to your Wagtail Admin interface and go to your HomePage
. You should now see the new "Text with Subtitle" block available within the StreamField. You can now add it, enter data, and save your page.
Creating Additional Custom Blocks
You can define as many block types as you wish to create rich and complex content. For instance, say you want to define a block type for a customized image gallery. You can then define it like so:
from blocks import StructBlock
class ImageGalleryBlock(StructBlock):
title = CharBlock(required=True)
images = ListBlock(ImageChooserBlock(), required=True)
class Meta:
template = 'blocks/image_gallery_block.html'
icon = 'image' label = 'Image Gallery'
You would also define the corresponding template (image_gallery_block.html
) for rendering the gallery.
Block Validation and Logic
Blocks in Wagtail allow you to implement sophisticated validation methods. To override or extend the validation or add extra logic, you can override methods such as clean
or get_context
.
For instance, here's how you could ensure the subtitle is always shorter than the title:
from wagtail.core import blocks
from django.core.exceptions import ValidationError
class TextSubtitleBlock(blocks.StructBlock):
title = blocks.CharBlock(required=True)
subtitle = blocks.CharBlock(required=True)
content = blocks.RichTextBlock()
def clean(self, value):
super().clean(value)
if len(value['subtitle']) > len(value['title']):
raise ValidationError('Subtitle must be shorter than the title.')
class Meta: template = 'blocks/text_subtitle_block.html' icon = 'edit' label = 'Text with Subtitle
Creating custom blocks in Wagtail allows developers to tailor a Wagtail CMS to specific content needs while providing the content editors with a dynamic and very user-friendly interface. And by being able to build structured, reusable blocks, you can improve the experience of the editorial team so much.
From simple text blocks to complex multi-field blocks, custom StreamFields provide the flexibility to create just about any kind of content structure you might need. Using the examples above, you will be well on your way to extending the power of Wagtail to fit your project's requirements.