New Wagtail Course! 🥳 The Ultimate Wagtail Developers Course

Tutorial Wagtail Version: 2.x

How to Subclass Wagtail Pages

Subclassing is having a class (in this case it's a Wagtail Page) that can be used for other classes (Wagtail Page's). The parent class has all the common attributes for the child pages, and every child page will inherit everything from it's parent. In this lesson we'll explore that by creating a subclassed Article and Video Blog Page that share a common parent, and then we'll extend the functionality of both subclassed pages by adding new fields.

Subclassing is a darn nice feature in Object Orientated Programming. It lets you write re-useable code in several places; much like a function, but bigger.

The great thing about subclassing Page's in Wagtail is reusability; you can create one "master" or "parent" page and let other pages inherit from it (child pages). All the children will share common attributes from the parent page, but then you can extend each child to be unique by adding custom fields and methods.

The analogy I like to use is a real family.

You share personality traits with your mother and father. If you have siblings, they will have similar personality traits to all of you. All of these common personality traits come from your parents, that's where they begin. And as their offspring, you'll maintain a lot of traits throughout your life, but you'll also grow into your own person. When you grow into your own person you'll gain new perspective, skills and personality traits. Or in the land of OOP, you'll have new properties, methods and purposes.

Below is a copy and paste snippet of code you can use as a reference in your projects to immediately make 3 blog pages: one parent, and two child pages.

``` """blog/models.py""" from django import forms from django.db import models from modelcluster.fields import ParentalManyToManyField from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel from wagtail.core.models import Page from wagtail.images.edit_handlers import ImageChooserPanel class BlogDetailPage(Page): """Parental blog detail page.""" custom_title = models.CharField( max_length=100, blank=False, null=False, help_text="Overwrites the default title", ) banner_image = models.ForeignKey( "wagtailimages.Image", blank=False, null=True, related_name="+", on_delete=models.SET_NULL, ) categories = ParentalManyToManyField("blog.BlogCategory", blank=True) content_panels = Page.content_panels + [ FieldPanel("custom_title"), ImageChooserPanel("banner_image"), MultiFieldPanel( [InlinePanel("blog_authors", label="Author", min_num=1, max_num=4)], heading="Author(s)", ), MultiFieldPanel( [FieldPanel("categories", widget=forms.CheckboxSelectMultiple)], heading="Categories", ), ] # First subclassed blog post page class ArticleBlogPage(BlogDetailPage): """A subclassed blog post page for articles.""" template = "blog/article_blog_page.html" subtitle = models.CharField(max_length=100, blank=True, null=True) intro_image = models.ForeignKey( "wagtailimages.Image", blank=True, null=True, on_delete=models.SET_NULL, help_text="Best size for this image will be 1400x400", ) content_panels = Page.content_panels + [ # ... FieldPanel("subtitle"), ImageChooserPanel("intro_image"), # ... ] # Second subclassed page class VideoBlogPage(BlogDetailPage): """A video subclassed page.""" template = "blog/video_blog_page.html" youtube_video_id = models.CharField(max_length=30) content_panels = Page.content_panels + [ # ... FieldPanel("youtube_video_id"), # ... ] ```
The Git Commit

The entire Git Commit can be found here: https://github.com/CodingForEverybody/learn-wagtail/commit/cbf0767201e760d96e2925354be2f28c0f8b820a

Related tutorials

The Ultimate Wagtail Developers Course

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.

Ultimate Wagtail Developers Course Logo