Tutorial Wagtail Version: 2.x
In Wagtail you can have two Richtext areas: a model field and a StreamField. In this article we'll cover the Streamfield type.
In Wagtail there are two ways to add RichText to your pages. In a previous article called Setting Up A RichText Content Area we explored how to add a RichText field as a model field to your page.
In this article we're going to add a RichText WYSIWYG editor to your streamfields for much more flexible content. That is, we're going to let the content managers place their richtext anywhere they like on the page.
If you're uncertain what a Streamfield is then you should read Wagtails page on Streamfields. It does a much better job of describing it's power than I typically do.
The first type of StreamField we're going to go over in this article is the basic StreamField. It can have multiple fields, much like a regular Django model, although we build it out differently than a regular Django model field.
Let's dive into some code and then I'll explain it all (I suggest you read through the code, line by line, just to get an idea of what's happening before the explanation; it helps with learning.)
Above is our demo page. Nothing major, it's a basic Wagtail page. But let's walk through this. Here's what this code does:
Page.title
field in the content_panels
Nothing crazy going on. So let's go ahead and add a StreamField section with a StreamFieldPanel.
This looks like a lot more. But it's not that much more, and I promise this will make more sense by the end of this tutorial.
The differences from the initial DemoPage class to this new version are:
streams
and it has a file called blocks.py
(see the comments below that line if that's beyond your skills right now)content
(It's not a special name. I've seen others use the word body
instead of content
¯\_(ツ)_/¯)CustomRichTextBlock
that comes from the blocks.py
file we imported in the second bullet pointStreamFieldPanel("content"),
to the content_panels
so Wagtail will give the StreamFields on our pages when we create a new page, or edit an existing page.If you run this code right now, it will break. blocks.py
probably doesn't exist yet, and if it does, then CustomRichTextBlock
probably doesn't. So let's go make that now.
You'll need to create a new Django app called streams (the name is unimportant as long as you import it correctly) and create a new file called blocks.py
in it. Or if you want to keep this tutorial simple, create a new file beside your models.py
file called blocks.py
. Either way, you'll need a blocks.py
file and you'll need to import it.
Inside of the blocks.py file add the following code:
Here we're not doing anything crazy either. In fact when you break this down, this is doing A LOT of work for you with very little effort.
richtext_content
and said it needs to be a RichtTextBlock
, and that it's requiredIf you save your files, run and apply migrations, and restart Django, you should be able to create a new page called Demo Page. And the content will look like this:
If you see what I'm seeing, you've successfully added a RichText StreamField to your DemoPage. If nothing was working for you, open your terminal and check the Django error outputs. The traceback should, hopefully, lead you right back to the issue.
At this point if you preview or view the live page you'll get an error saying there's a missing template. No big deal, let's add the demo_page.html template and then we'll add the custom_richtext_block.html template.
We got the name demo_page.html from the DemoPage class we created at the start of this tutorial. The template property tells us where to find this file. If you're new to Django and Wagtail, this template file should be under templates/demo/demo_page.html
Now let's add the RichText StreamField template.
Fun fact: all streamfields can use a template file, get rendered, and be injected into your for loop in your demo_page.html template.
That's all there is to setting up StreamFields, really. And this one takes care of rendering out the WYSIWYG data too.
Bonus Feature:
Wagtail will also strip unaccepted elements from the WYSIWYG editor too. So if you think someone might be trying to add a <script> in there and perform an XSS attack on your website, it won't work. Wagtail's editor (called Draftail) will strip it out. Security is sexy.
Your page will now have rendered RichText on it.
More often than not, you'll want to add more than just RichText. Maybe you want a special image, or a special title, or to give the content entry people a way to select the background color. It could be any number of reasons, but let's go with: content entry people want to change the background color.
Simple enough. All we do is add a Wagtail ChoiceBlock and put it in to the template. Add the ChoiceBlock to your StreamField, like so:
And when you save and reload your DemoPage, you'll see an option like this:
Pick a color. By default we said the background color should be white. But let's make it really gross so it stands out and we know if it's working or not... let's make it browser-default blue. Open up your StreamField template and add the color.
All we did was add {{ self.bg_color }}
inside the inline CSS. You can do this will full CSS classes since it's cleaner that way. But you can also perform logic on this such as {% if self.bg_color == 'blue' %}color: white;{% endif %}
and that'd change the text color to white, with a blue background. We didn't add that logic in, so let's take a look at this terrible design.
So as we can see, we've now built a StreamField with a RichTextBlock and a ChoiceBlock to give the content entry people a choice of background color.
But wait, there's more!
What if we just wanted to give people a RichText editor in their StreamFields without any additional fields? In this case, let's say the background color was never going to change and it's simply a WYSIWYG editor that outputs RichText somewhere in the sea of StreamFields.
Let's create a second RichText StreamField. The following code belongs inside of blocks.py.
The biggest change here is that we didn't inherit blocks.StructBlock
, but instead we inherited blocks.RichTextBlock
directly. The Wagtail Core team did a fantastic job making StreamFields so darn flexible that we can directly inherit a StreamField without needing to make everything a StructBlock.
But this won't work.. not yet. Open your demo/models.py file (where the DemoPage class lives) and add this StreamField to your content field.
Save and reload your Demo Page inside the Wagtail Admin. And you'll see two RichText StreamField options now. And when they're both expanded, they look something like this:
The last thing we need is a new template. If you recall, we set the StreamField template of our independent RichTextBlock to point to streams/custom_alone_richtext_block.html. So let's create that file now.
When it's all said and done, you'll have two different StreamFields using the RichTextBlock in different ways.
Before I show you what the final page looks like, remember we created a StreamField with the ugly blue background. I've kept it in this image on purpose so we can see the distinct difference between the two different StreamFields.
Some people want to read the article, some people just want the code. I don't judge ¯\_(ツ)_/¯
Here's a Gist with all the goodies in it.
Setting Up A RichText Content Area
Posted on
In Wagtail you can have two Richtext areas: a model field and a StreamField. In this article we'll cover the model field type.
03. Setting Up Allauth In Django
Posted on
Setting up Django Shell, Shell Plus and IPython
Posted on
Django comes with a python shell where you can import your models and test things out. It's not great out of the box, but we can make it better by using shell_plus (installation instructions are inside) and letting IPython take care of interactivity. This is all helpful for learning Wagtail.
04. Setting Up Validation Login With Allauth in Django
Posted on
This course covers everything from basic installation to advanced features like custom blocks and API integration, it's perfect for developers looking to enhance their skills with this powerful CMS.