class BlogPage(Page): """ A Blog Page We access the Person object with an inline panel that references the ParentalKey's related_name in BlogPersonRelationship. """ introduction = models.TextField(help_text="Text to describe the page", blank=True) image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", help_text="Landscape mode only; horizontal width between 1000px and 3000px.", ) body = StreamField( BaseStreamBlock(), verbose_name="Page body", blank=True, use_json_field=True ) subtitle = models.CharField(blank=True, max_length=255) tags = ClusterTaggableManager(through=BlogPageTag, blank=True) date_published = models.DateField("Date article published", blank=True, null=True)
Blog posts support multiple authors through the BlogPersonRelationship model:
bakerydemo/blog/models.py
class BlogPersonRelationship(Orderable, models.Model): """ This defines the relationship between the `Person` within the `base` app and the BlogPage. This allows people to be added to a BlogPage. We have created a two way relationship between BlogPage and Person using the ParentalKey and ForeignKey """ page = ParentalKey( "BlogPage", related_name="blog_person_relationship", on_delete=models.CASCADE ) person = models.ForeignKey( "base.Person", related_name="person_blog_relationship", on_delete=models.CASCADE )
The authors() method returns only live (published) authors:
def authors(self): # Only return authors that are not in draft return [ n.person for n in self.blog_person_relationship.filter( person__live=True ).select_related("person") ]
Blog posts use Wagtail’s tagging functionality through ClusterTaggableManager:
bakerydemo/blog/models.py
class BlogPageTag(TaggedItemBase): """ This model allows us to create a many-to-many relationship between the BlogPage object and tags. """ content_object = ParentalKey( "BlogPage", related_name="tagged_items", on_delete=models.CASCADE )
The get_tags property enhances tags with URLs:
@propertydef get_tags(self): tags = self.tags.all() base_url = self.get_parent().url for tag in tags: tag.url = f"{base_url}tags/{tag.slug}/" return tags
class BlogIndexPage(RoutablePageMixin, Page): """ Index page for blogs. We need to alter the page model's context to return the child page objects, the BlogPage objects, so that it works as an index page RoutablePageMixin is used to allow for a custom sub-URL for the tag views. """ introduction = models.TextField(help_text="Text to describe the page", blank=True) image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", help_text="Landscape mode only; horizontal width between 1000px and 3000px.", )