Wagtail CMS: Using a SnippetChooserPanel to Select Multiple Blog Authors (Snippets + Orderables)

This video is from Wagtail CMS 2023 .

Wagtail CMS: Using a SnippetChooserPanel to Select Multiple Blog Authors (Snippets + Orderables)
0:18:49
Published November 29, 2023
9,342 views
144 likes

This is part 2, coming from the previous article/video. In this lesson we'll be using a SnippetChooserPanel to select Blog Authors (a snippet we registered last episode). We'll also add in an Orderable to our Blog Detail Page so we can select between 1 and 4 Blog Authors.

Tutorial: https://learnwagtail.com/tutorials/using-snippetchooserpanel-select-multiple-blog-authors-snippets-orderables/

Git Commit: https://github.com/CodingForEverybody/learn-wagtail/commit/18c4346541d78e73342e7bcdcbe85852c3257d9e

Learn Wagtail from scratch with the official Wagtail for Beginners Course
https://learnwagtail.com/wagtail-for-beginners/

Used in this video: Wagtail 2.4, Python 3.7, Django 2.1.5 #Wagtail #Django #Python

Summary

The speaker shows how to let editors assign one or more snippet-based blog authors to a Wagtail blog detail page using an orderable model. The orderable uses a parental key to connect each author entry to the page, a foreign key to the registered BlogAuthor snippet, and a SnippetChooserPanel so editors can select authors through Wagtail’s interface. A multi-field panel adds the authors to the edit screen with a minimum of one and maximum of four entries, while the template loops through the orderables to display each author’s name, optional website, and resized image. The speaker also explains the template relationship between the orderable and its related BlogAuthor record, and runs migrations to create the required database model.

Key takeaways

  • An orderable stores repeated entries of one specific type and allows editors to reorder them.
  • A parental key connects the author orderable records to the BlogDetailPage, while a foreign key connects each record to a BlogAuthor snippet.
  • SnippetChooserPanel provides Wagtail’s snippet-selection interface instead of a basic dropdown field.
  • A multi-field panel with an inline panel can enforce minimum and maximum author counts, such as one to four authors.
  • In the template, each orderable’s related author data is accessed through the foreign-key field to display its name, website, and image.

Summarised automatically from the transcript.

Transcript

3,245 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:00

Hello, welcome back to another lesson on learning Wagtail. In the last lesson, we learned how to create a new Django model and register it as a snippet. In fact, we actually learned about snippets for the first time in it in the previous lesson. And what we were trying to accomplish was the ability to select multiple blog authors or even a single blog author. from a snippet. Now we didn't get all the way through it and in this lesson we're going to use orderables. So we're going to add some I'm going to say we're we're adding some complexity here to our blog detail page. And the idea is that at the end of this, someone will be able to Grab multiple blog authors at any point in time and at any point in time you will be able to edit a blog detail page and say that it was

0:49

edited by or was published by or it was authored by a particular person that came from our snippets data model. Now if that doesn't make sense, just bear with me. This gets easier, I promise. Now I'm just gonna go ahead and start my server. So Python3 manage. py run server. If you're coming from that last episode Uh I was running in port 8001. I went and turned off whatever was running in port 8000, and now I can use 8000 again. Uh so just note that there was a jump from 8001 to 8000. And again, in our last episode What we did was we added snippets in here. So we have blog authors and we created two of them. So Caleb and Jacob. Now in this lesson, uh da-da-da-da-da-da.

1:34

Let's go into our blog and let's edit blog post number one. We want somewhere in here where we can select one or more blog authors. So let's jump right into that. And the first thing we're going to need to do is we're going to want to create some sort of orderable. Now, if you are familiar with orderables, great. If you're not, a quick little recap on what an orderable is. An orderable is much like a stream field, but the Data that it holds is basically one type of data. So an orderable can be, for instance, uh being able to select multiple blog authors and putting them in a certain order. Whereas a stream field can have multiple types of data. Where a stream field can have like a call-to-action stream field, it can have maybe a banner or a carousel or something like that.

2:21

An orderable is a lot more specific, and it's locked down to a specific part in your template. So let's go and create an orderable and let's call it class. blog authors orderable. The name is not really too important to be honest with you. And this allows us to select. One or more blog authors from Snippets Lemony Snippets A series of fortunate code. Page is equal to where is this going to link to? Okay, so again, if you're familiar with orderables, this is pretty straightforward. If you're not, then this page basically has to link to.

3:07

another actual page. It has to be a Wagtail page. And we do that with this this class called parental key. And this takes blog dot blog Detail page, if I recall, that is in fact what we called it, but I'm going to double check. Blog listing page, blog detail page. So it just takes this as a parameter. Takes that as a string and this one definitely needs a related name. So the related name, we'll move that up for you. That related name is going to be blog authors And so this just says that this orderable is attached to the blog detail page. That's all that's doing. And in fact Inside of our code, we never even use this variable. Next we want to actually select our author, so we're going to have author is equal to.

3:55

Now because this is going to a Django model. Which is our blog author in here. It's a Django model. We want this to be a foreign key. So we're gonna do models. forein key. And I'm gonna put in here blog. blog author. And on delete is equal to now let's do models. cascade because we I don't think we've done that yet. I've always just been setting things as null, but let's set this one to cascade. Now this is groovy, and this is going to create some data for us when we run our migrations, but this is not everything we need. Uh first and foremost I don't think this is even imported. Orderable might not even be imported. We'll talk about imports in just a moment and and actually import things

4:41

But we know that everything in Wagtail lives under this concept of panels. So even though we have an author here and we want to be able to select our author, this needs to live in some sort of panel. So let's put panels is equal to and it's a list and this one is a snippet chooser panel. Now if you're asking me, Caleb, why is this a snippet chooser panel? Why is this not a field panel? Why is this Not a multi-field panel. Why is it specifically a snippet chooser panel? To answer that for you, the last lesson we created this blog author. It's a Django model, and at the very bottom we registered this as a snippet. Now if you just gave us a field panel, chances are this would just be a drop-down box for you, so a select box. But we actually want Wagtail's nice interface, so we get a snippet chooser panel, so we can go and

5:29

look for certain blog authors if we wanted to. So let's go ahead, let's run this, and yep, we can see here that Flake 8 is complaining. Orderable is not imported. Let's import that. That comes from Wagtail Core Models. Orderable. Alright, that underscore is gone. It's not parent key, it is parental key. Thank you, Flake 8. This is why we use linters. And this one comes from modelcluster dot fields. Where is it's not in there? So let's import it from modelcluster. fields import. Parental key. Thank you VS Code for autofilling that for me. And lastly we have snippet chooser panel. So this is just like an image chooser panel. Where it says from Wagtail.

6:15

images. edit handlers, or in the case of a regular field panel from Wagtail. admin. edit handlers, this one is basically the exact same thing. So from Wagtail dot snippet. Edit handlers, import, snippet chooser panel. That's all that is. Nice and easy. So we have no more complaints in there. Let's check out our terminal Terminal velocity looks good. Actually that'd be a great name for a terminal. Velocity. Okay, let's cancel this and let's make migrations. Make migrations. Python 3 manage. py migrate to those migrations. Life looks good. Python 3 manager. py run soiva

7:00

So basically all this did was it created a model called Blog Authors Orderable, and then we applied it to our database so that there is actually a table called blog authors orderable in our relational database. Now there are just two things we need to do. First is we actually need to enable this. So let's go down. Let's go down. Smooth scrolling for the win. Blog detail page. This is where we want to be able to select our authors. So let's go down to content, nope, content panels, rather. And let's add a new multi-field panel in here. Multi-field panel. And I want a multi-field panel specifically because I can name it. I can put a little heading with it. This is just going to take an inline panel, inline panel, and we give it the related name.

7:47

So blog authors. This is the related name that matches. Do do do do do. This related name right here. So in our orderable has there's a related name and we're going to use that related name here Label. What is the label? It's called an author. So like what are you adding? Are you adding an author? Are you adding a post? Are you adding a person? In this case, we're adding an author. Minimum num. Min num. Min num is equal to one. There must always be a blog author. And let's say max num. Because let's say for whatever reason someone wanted to be a little malicious and just like hijack our page with SQL queries because they could select a thousand blog authors. Let's maybe prevent that.

8:32

And let's give that a maximum of I don't know, four. That seems pretty that seems pretty good. And let's give this a heading for our multi-field panel, and we'll call this authors, maybe. Comma, comma, comma, chameleon. Inline panel is not imported. Inline panel is a standard panel, I know that. So that comes from Wagtail Admin Edit Handlers. My terminal looks a-k and when I refresh my browser and I'm just on a blog edit page here, blog detail page. We can actually see that from the top here we have our title, we've got our custom title, we've got our blog image, and we have authors. And we said there needs to be a minimum of one, so let's go ahead and publish this and it will complain.

9:20

Yep, this field is required. Please submit one or more forms. Groovy groovy. So I'm gonna select me And when I publish, oh look at that, I am published. And when I go back to edit this page, there it is. And now if I wanted to add more, I could, up to a maximum of four. These are all required fields, so if you were to save this, it's going to complain that these fields are empty. Yeah, just like that But again, we could reorder them. That's the nice thing about orderables is we can reorder them. We can add multiples. We can limit them. We can say that there needs to be a minimum or a maximum number of them. This is really really good for blog authors. Now what I'm gonna do the last thing we need to do because just a couple minutes ago I said that there are two things we need to do.

10:05

The second thing we need to do is we need to add this to our template. And at this moment in time, this is a pretty boring blog post, but there's no signifier, there's no way to visually see who this author is. So we're going to need to add that. Let's go ahead and open blog detail page. And where do we want this to show up? Maybe just under the title So we have a title in here, text center, and what are we gonna do here? In this next section, I just want to give you a heads up. This is going to be ugly. This is not going to look nice. I'm going to make it look nicer behind the scenes so you don't have to watch me write a bunch of HTML and CSS and tinker with styles and things like that. Because this is a Wagtail course, this is not a bootstrap course, I'm going to cut out the bootstrap stuff.

10:53

So if you if you pull down this commit, or you're even looking at the commit and you're like, oh, I don't remember Caleb talking about this, well, this is exactly why. So just a heads up, don't be shocked when you see that. So let's add a list in here. And in this list we want We want a name and an image and a website. Websuit website. Now this is where it gets a little bit tricky. Just these four loops. and the association between data models, it gets a little bit tricky for some people. So what I'm going to do here is write for, because I'm going to loop through something, for each author in self. blog authors. And we are going to get

11:42

a list for each one. Now, should this work appropriately, we will see that there is one list item in here. And it's not n4, it's end for. Not to be confused with endor. Deferring related manager, you know what? Honestly, I should have seen that coming. This one gets me every single time. So we need to loop through self. blogauthors. all. We need to get all of them. Otherwise we're trying to loop through a single model when actually we want the data behind the model. And here we have name image website. And let's go ahead and add one more in here so that we can see the power behind using an orderable. So let's add Caleb and let's also add Jacob. Publish.

12:28

And I'm going to refresh my page and this will show up twice. As expected. No big deal there. But now we actually want the name, image, and website. So let's start with a name first. You think the name would be author. name. And if you're thinking that, well it's because the rest of us were thinking that too. And the trick behind an orderable is that that's actually not how this works And to explain this, we have a multi-field panel, multi-field panel, where are you? Blog detail page. We have a multi-field panel with an inline panel of blog authors. So this is saying. Basically, there could be one or more blog authors, that's where we get the dot all from, but up here We're not looping through this author or these authors.

13:15

We're looping through each orderable, so we're looping through each dataset of this. And we're going to get that author. Now that author also has additional details with it, has additional data. That author is associated, because it's a foreign key, it is associated with blog author model, which has name, website, and image. So here's the tricky part. Is we're doing for author in self. blog authors all. We want author. Now to make this simpler what you can do is you can actually make this less explicitly named, which I know so far is pretty weird for me, but this actually helps a lot of people out. So instead of writing author, what you could write is uh loop or something, or for iteration.

14:00

So for for each iteration For each iteration in our self. blog authors, we want that iteration that's in here. author, that's a foreign key to here, in here, and then we want that name Now, unfortunately, there's not really a better way to describe that, I don't think, other than basically we're traversing through different tables in our database. So if I am to refresh this page, I will see the name Caleb Tullian and Jacob Tavlian. And let me make this larger. For people who are watching this on their phones or tablets. Says Caleb Tullian and Jacob Tavlian. Now we also have a website and we also have an image.

14:47

We know the website is optional, but we know that image is mandatory. So let's first start with a website. Let's do if iter. author. website And if, and we're gonna call this uh da da da da da da da iter. author dot website because this is a URL field, so it's going to have the website URL in there and we're just gonna call this website. In fact, let's do it in parentheses. So this one is linking to learnwagtail. com. We can see that when I open this. LearnWagtail. com. And this one goes to codingforeverybody. com.

15:33

So those websites are now customized. And a check to see if there is a website because it's optional. Lastly, we need an image. So let's go ahead and create a small image rendition for each person. So let's do Wagtail Image. Iter dot author dot image and again we're iterating through the self dot blog authors. We're going to then Loop through all of these. That's what I mean by iterating through the blog authors. We're going to grab that author, which matches our name in here. And because it's a foreign key to a blog author, we can also access image, website, and name So we have iter. author image, and I'm going to fill this with 100 by 100 as just an image.

16:21

Image. url and I don't want the alt name in there to be the image alt name. I want this to be the Iter. author dot name because that is a better name. And when I refresh, hello! That's definitely not me, but that image shows up, so that's pretty nice. When we zoom back out, this is probably gonna look better if it's smaller. Nope, it doesn't. That is a large image still. So let's go ahead and make that smaller. Making it smaller 50 by 50. There we go. So we have a list of blog authors in here. And just as one more example, let's go ahead and delete one of them. Let's go ahead and get rid of Jacob Tavlian

17:06

because he is not a real person. I mean he might be a real person, I don't actually know. And when I refresh the page, here we go. It's just me with a link to a website and my photo. So that is all there is to know. There is a lot covered in this lesson. We covered orderables again. So if you're brand new to orderables, you learned all about orderables. If You already knew about orderables, then cool. But we also learned about Snippet Chooser Panel, which allows us to select A registered snippet, which is from the previous lesson. So if you're not familiar with snippets yet, you're going to want to watch that previous lesson all about snippets And lastly, as a visual recap, all we did here, shouldn't say all we did, this is actually a really cool feature, is we added a multi-field panel called Authors.

17:55

And we are able to have one or more authors in here because we set a minimum number of one, there always has to be one, maximum number of four, doesn't let us add more than four, and then we can loop through them in our template. If at any point in time you're scratching your head, you're thinking, Caleb, what is going on here? Feel free to check out the git commit. I will put the link in the description down below so you can always check that out. You can check out the entire repository if you wanted to, but I'll also link specifically to that commit. And hey, if you like this video, if you learned something from it, don't forget you can subscribe, you can share, you can comment. My name is Caleb Tallin. I am the voice behind these videos. If you like this video, there are several more at learnwagtail. com. There's other tutorials on there as well. And naturally, if I went a little too fast and you want to read more about the documentation, that's totally cool too.

18:45

Wagtail has great docs at docs. wagtail. io.

Questions this talk answers

What is an orderable in Wagtail, and how is it different from a StreamField?

An orderable holds one specific type of data, such as multiple blog authors, and lets editors arrange those items in a defined location. A StreamField can contain multiple kinds of content, such as calls to action, banners, or carousels.

Discussed at 1:34

How do I create a Wagtail orderable for selecting blog authors?

Create a `BlogAuthorsOrderable` model linked to the blog detail page with a `ParentalKey`, give it a related name such as `blog_authors`, and add a foreign key to the `BlogAuthor` snippet. The orderable’s panels then expose the author field in the Wagtail editor.

Discussed at 2:21

Why use a SnippetChooserPanel instead of a FieldPanel for a blog author?

Because the author is a Django model registered as a Wagtail snippet, a `SnippetChooserPanel` provides Wagtail’s snippet-selection interface. A regular field panel would generally present it as a basic dropdown or select box.

Discussed at 4:41

How can I require and limit the number of blog authors on a Wagtail page?

Add an `InlinePanel` for the orderable inside a `MultiFieldPanel`, then set `min_num` and `max_num`. In the example, the page requires at least one author and allows no more than four.

Discussed at 7:47

How do I display multiple orderable blog authors in a Wagtail template?

Loop over `self.blog_authors.all`, which returns the orderable records, and access each linked snippet through the orderable’s foreign key, such as `iteration.author.name`, `iteration.author.website`, and `iteration.author.image`. This also lets the template preserve the editors’ chosen order.

Discussed at 12:28

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos from Wagtail CMS