Video Tour of Wagtail 8.0
Published September 19, 2026
This video is from Wagtail CMS 2023 .
When you start to create several different page types in Wagtail and you create a child page (a page that's nested under a different page) you'll see every single page is an option.
Well that can be a problem on larger sites. You probably don't want a HomePage living in your BlogListingPage. And you probably don't want a BlogDetailPage to be a HomePage.
In this video we'll explore how to restrict where pages can live by telling the parent page what types of child page(s) they should expect, and by telling the child pages which parent page(s) they can expect.
Tutorial: https://learnwagtail.com/tutorials/restricting-parent-and-child-pages/
Git Commit: https://github.com/CodingForEverybody/learn-wagtail/commit/c4cf47b16221b71a4f2bf4419590400df25333df
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
Outro Template made by Grabster - Youtube.com/GrabsterTV
#Wagtail #Django #Python
Wagtail page models can enforce a clear site hierarchy by controlling which child page types are allowed beneath each parent. The speaker shows how to use `subpage_types` to allow only appropriate children—or an empty list to make a page a dead end—and `parent_page_types` to restrict where a page can be created. They also demonstrate `max_count = 1` for singleton pages such as a blog listing page, and explain that these restrictions guide content editors, prevent invalid URL structures, and simplify application code.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Hello and welcome back to another lesson on learning Wagtail. We recently just finished up a little sub-series on the Wagtail V2 API and creating a headless CMS. We did not go into any of the front end work because I would like to leave that as unopinionated. So maybe you prefer View or React or Angular. Either way, I'm not going to force any of those on you. This is a Wagtail course. And so we talked about enabling fields, enabling the API, JSONifying images, getting image renditions, all sorts of good things. And now it's time for us to take a little bit of a turn. So let's get out of Wagtails headless CMS API goodness, and let's talk about some user flow for a moment.
And by user flow I mean when you open up your website, so I'm at localhost port 8000 slash admin, and I go into my homepage. And let's say I wanted to add another page in here. So I add a child page. And I can add a article blog page, a blog detail page, blog listing page, contact page, flex page, or a video blog page. Now this is all good, but this gives our content entry people absolutely no guidance whatsoever. So if you put on your content entry hat. . And you're thinking about entering content, maybe you're writing a blog post and you're in the homepage and you just click the click the add child page because you're like, yeah, I want to add a new page. So you click that and then you add a new blog detail page.
Well, that blog detail page is going to live underneath your home page Now in most instances that's not what you want because you're going to have a very weird URL structure. And by a very weird URL structure, what I mean is you might have uh so this would be your home. I'm gonna make this bigger. So this would be your home URL, and then you would have your blog listing page, and then you would have your blog detail page. So detail page one. Something like that. But if someone can go into the homepage and create a blog post, they are now creating blog detail page two. But this one does not live under blog. Actually what I should have done was
that. So now we have your website. com slash detail page two when it should actually be blog detail page two. So we want to sort of force that page hierarchy. Now the way we do that is by telling Wagtail where it can place pages. So for instance, when we click Add Child Page A video blog page and an article blog page and also a blog detail page should be only accessible under the blog listing page. And that blog listing page should only ever have maybe one instance. Because why do we need more than one blog? Yeah, maybe your site does need more than one blog. But let's go ahead and say that the article blog page, uh, we're going to get rid of the blog detail page
and the video blog page need to live underneath the blog listing page. Okay, we can do that. I'll show you how to do that in just a sec. Now if we go into blog and I add a child page, well underneath the blog, I can now add a contact page, a flex page. I can add other blog listing pages or detail pages. I can do all sorts of things in here. So really it's a free-for-all of where you can put any page at any point in time. And a good design will limit that Now if this sounds weird to you, it's just because it's a brand new concept, but believe me when I say your clients are going to appreciate that type of guidance. If they can create pages of any flavor anywhere in their website, it's going to cause a lot of confusion. And that might actually conflict with some of the code that you end up writing.
So what we want to do is create a forced hierarchy, and that guides them along the way. So let's take a look at our homepage again. So we've got. Home and we want to when we click add child page we want to get rid of the blog article pages. So let's limit what can be in here. So let's open up our editor and go to home. models and we want to find our homepage homepage homepage homepage and where it says max count which is how we would limit the number of blog listing pages as well It says, there can only ever be one homepage. Like a Highlander, there can only ever be one. We want to give this a subpage types.
And this property is simply a list. And this list is going to take your app name. yourmodel name. And so the subpage types that we want to enable in here We're actually going to ignore the ones that we don't want. So we're going to allow a contact page, a flex page, and a blog listing page. So let's type in here blog dot blog listing page Not a new line. Contact. Contact pages, that what I called it. Contact models. Contact yeah it's called a contact page. Okay, contact dot contact page and flex models and that one's called a flex page. So let's throw this on new lines
Let's add flex and flex page. Okay, save, wait a second, let your server restart itself, and when we go back in here and hit refresh , ta-da! They're all gone! So now, under your homepage, you can only ever create a blog listing page, a contact page, and a flex page. Now actually let's let's go over the blog listing page one. I mentioned it, we might as well go over it. We already have a blog listing page. We can see that here. So when someone goes to add a new page, should they be able to create another blog listing page? I don't think so. So let's go into blog models and let's go into our blog listing page. And
Let's type max count is equal to one. Again, wait two seconds, let Django restart itself. Refresh your page and that's gone too. Now that one's actually gone because we already have one of those. That's saying you can have a max number of blog listing pages to be one. So, we already have one. It's not going to allow us to create any other ones. It's a nice feature. So that cleans up our homepage. Now We have uh several other pages in here, so let's go to pages. We have home, blog. Yeah, let's take a look at blog. So in our blog listing page, that's this page, that's that's the one that we're looking at right here. When I click Add Child
page, you can see that I can add all sorts of things in here. Now maybe I don't want a contact page and I do not want a flex page underneath the blog listing page. So we type sub page underscore types is equal to, and again, this takes a list. I'll just make that a little bigger. And this one is going to be the type of pages that are acceptable. Now we only want a blog article page. I think that's what it's called. Blog. So we've got a detail page. What is that one called? Just an article page? Article blog page. Yeah, it's because I named that one funny. And a video blog page. So we have sub pages and we only want the blog video page and the blog dot article blog. Page.
Very simple. Now when I refresh this page, it's only going to give me two options. Beautiful. Okay, so let's get out of this one and let's say that we are editing a blog article page. So we want to maybe add a child page. Actually, scratch at. Let's do this one a little bit differently. You can see that under an article blog page, we can actually add child pages, and we can add pretty much any child page that we want. that allows the max length to be satisfied. So we cannot add a blog listing page because there's already one of those. But we can add Blog detail page after blog detail page after blog detail page. Now let's say this is the end of the line. Let's say we don't want our content people to make any more pages underneath our blog pages.
So we go back into our editor and let's look at our blog detail page. Detail page. There we are. And this blog detail page. should have no pages nestable underneath it. It's the end of the line. As far as the URL and the page hierarchy goes, this is the very last one. It's the furthest one out there. So we type Subpage types is equal to and we simply give this an empty list. It says there's nothing in there Save, wait two seconds, come back here, and refresh our page, and we're going to see that that little plus when I was hovering is no longer there. And if I go to View this page, all I can do is edit it.
I can't add a child page, I can edit, I can view, and I can copy. And that is about it. So now lastly we have a couple more that we want to do. We've got a flex page in here, so let's check out our about page. Let's add a child page Well, under this about page or this flex page, this general web page, we can do anything And maybe we don't want to do that. Maybe we want flex pages to be nested underneath flexible pages. Oh, maybe we also want a contact page, but we don't want anything else. So let's open up our flexmodels. py. We have a flex page in here, and let's add subpage types is equal to it's going to be itself. So
flex. flexpage And we also wanted the contact page, which is contact got contact page. Save, wait two seconds, refresh Ta-da! So now we're really limiting what pages people can create underneath other types of pages. Another one that we have here is our contact form, right? Underneath the contact form, we can have anything. But really, should you have Anything underneath the contact form? I'm not going to tell you that you should or shouldn't, because that's completely up to you and your application. But if you did want to make it the end of the line. . So that it can have no child pages underneath it, you simply type subpage underscore types is equal to an empty list
And now I'm going to refresh this page. You're going to see we get a 403. That's good news. And we don't have an add child page in there at all anymore. Now this will cover most of your scenarios. It won't cover all of them though. So what if we went into pages? This is our root and we said add child page here. Well, we are now able to make any page a homepage. And we don't want that. We only want the homepage to be to be the homepage. So let's get rid of some of these and let's unrestrict our home page. So let's close these up and let's go to home models. Subpage types, we already have that in there. Let's comment out our max count.
And we're going to see that homepage shows up in here. And now we want. to add a different type of field called a parent parent page type. Now what can this parent page type ever be? Because we have max count of one, and generally when you set up a website, you're going to set it up to be the homepage as your sort of root page for your website. This is sort of a redundant example. However, let's take a look at this anyways. So the parent page type is going to be a WagtailCore dot page. And what that is saying is page ID number one, which is our root, we can see this, it's our root page, this is where it can live We're saying that the homepage fix that up there. We're saying that the homepage can only live underneath the root page.
So we cannot nest it anywhere else So that's another way of limiting it. Now what happens if we want to get rid of all of our blog detail pages? So let's open up blog models up high and we've got a blog detail page and we have parent page types is equal to where can this live. Well, we only ever want this to live underneath the blog listing page. So let's do this, blog. blog listing page. And let's save that. Now this is going to affect three pages because the blog detail page is actually being inherited from the doo-doo doo doo-doo. The article blog page. You can see it's being inherited here And you can also see that the video blog page is inheriting the blog detail page as well. So let's go back to our blog detail page.
Refresh, and we can no longer create these types of pages as a homepage. And lastly, we need to clean up our flex and homepage. So let's go. flexmodels. py and let's say a flex page can only ever live underneath certain page type. So parent page type is equal to a list. And where can the flex page live? Well it can be nested underneath flex. flex page. That's allowed. It is not allowed to be nested underneath a contact page, so uh we don't really need to do that because the contact page is already taking care of that one with the page subtypes Uh and this one can also be created underneath home. home page
Save that and we'll see that flex page disappears. And lastly, let's get rid of contact page. So contact models. py Parent page types is equal to, and the only page type this one is allowed to be living under, the only parent it's allowed to have is home. homepage And when I refresh the page, as you just saw, Wagtail said, there's only one page type this could possibly be, so let's just assume that they're going to add a new home page. Now, we don't want to add a homepage. We already have one. But if you wanted to have a multi-site installation of Wagtail, you could easily create more than one homepage.
So now we have one homepage here, but if we wanted to have a multi-site instance, uh you could also create another homepage. It's going to use the exact same homepage, and you could host a subdomain or a different site on here. Alrighty, so that's about all there is to know. We have really cleaned this up. So if we go in here and let's say uh I wanted to add Um but but blog listing page. Did we do this one? Add a child page to the blog listing page. Yes, we can only add the video blog page and the article blog page. We can't add a listing page under a listing page under a listing page. We cannot add blog detail pages after blog detail pages after blog detail pages. They can all still live in here, but this one is a dead end. We cannot put a child page underneath any of the blog pages.
So effectively what we have done is we have guided our user to creating certain page types in certain areas. Now that's going to follow a strict design rule, which is a very good idea when you're making a website And again, if you put on your content entry hat or your client hat and you think, what page am I supposed to put where? Well, this sort of guides them. This makes it really easy. Under blog, if you wanted to add a blog page, you can add a video blog page. Pretty self-descriptive in my opinion. It's a blog that has a video in it. And an article blog page is a blog page that is written instead of in video format Nice and simple. And again, if this sounds a little bit weird because you're actually restricting your clients or the content entry team from
doing anything they want, this is actually a very good thing. It simplifies their lives and it makes content entry easier, makes following a design easier, it makes debugging easier, it makes writing your code easier because now you don't have to consider every possible scenario. Like for instance, if you wanted all of the child pages of a blog listing page. Well, you know that there are no there are no grandchild pages, so all you have to do is get the child pages. And that is that. So thanks for tuning in on this lesson. Uh it's taken a little bit of time for us to get here, but I think we had enough pages to finally explore this. My name is Caleb Tallin. I am the voice behind the videos. Again, thank you for joining me here. You can find more videos like this and tutorials on learnwagtail.
com. If you want to learn more about these particular sub pages or parent page types, of course that's available in the docs at docs. wagtail. io. And if you found this video helpful, don't forget you can share, you can subscribe, and you can comment. If you want to see the source code, the git commit is in the description down below. And if you want to binge watch all these videos, click that little rectangle at the top right, and you'll be able to see all the videos in this playlist on YouTube.
Set the page model’s `subpage_types` to a list of permitted page types, using the app label and model name, such as `blog.BlogListingPage` or `contact.ContactPage`.
Discussed at 4:40Set `max_count = 1` on the page model. Once one instance already exists, Wagtail removes that page type from the Add Child Page options.
Discussed at 6:14Set `subpage_types` to an empty list. The Add Child Page option disappears because the page becomes the end of that hierarchy.
Discussed at 8:33Use `parent_page_types` to list the only permitted parent models. For example, a blog detail page can be limited to living under a blog listing page, while a homepage can be limited to the root page.
Discussed at 11:41It guides content editors into the intended site structure, reduces confusion and invalid URL hierarchies, and makes the application easier to code and debug because fewer page arrangements need to be handled.
Discussed at 15:39Note: 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.
Published September 19, 2026
Published July 9, 2026
Published May 20, 2026
Published April 16, 2026
Published April 1, 2026
Published March 10, 2026