I am setting up a Wagtail website.
There will be an Event Index page with Events as child pages.
Each event page could also have child pages, if it is part of a event series.
The main event will show the child events as a series of links on the page. The child events also need to display the parent event and also its own siblings.
In models.py I have an Event class. So far I am detecting children, siblings, parents like this:
@property
def childpages(self):
event_children = Event.objects.live().descendant_of(self)
return event_children
@property
def parentpage(self):
event_parent = self.get_parent()
return event_parent
@property
def siblingpages(self):
event_siblings = Event.objects.live().sibling_of(self, inclusive=False)
return event_siblings
Is there a way of finding out what the parent page type is? If it is the event index I wouldn't want to display it on the event page. I also wouldn't want the main event pages to show siblings.
I've tried various things with not_child_of(somepage) but not quite sure how to use this. What does 'somepage' reference? A class, a variable? I'm used to Javascript and pretty new to Python.
Here's how I'd write it:
@property
def parent_event(self):
parent_page = self.get_parent()
if parent_page.specific_class == Event:
return parent_page.specific # or just `return parent_page` if you don't need the extra detail from that page
else:
return None
@property
def sibling_events(self):
parent_page = self.get_parent()
if parent_page.specific_class == Event:
return Event.objects.live().sibling_of(self, inclusive=False)
else:
# this is not a child event, so don't return siblings
return Event.objects.none()
In Python, the standard way of checking whether an object is an instance of a given class (i.e. in Wagtail terms, whether a page is of a particular type) is isinstance(parent_page, Event)
.
However, with Wagtail there's an extra complication - when you traverse up and down the page tree using methods like get_parent
and get_children
, there's no way for it to know in advance which page type it's going to get back - so, for performance reasons, it will return a "minimal" object of type Page
which includes just the properties like title
that are common to all pages. So, self.get_parent().title
would work, but self.get_parent().start_date
wouldn't. To turn that into a "real" object of the proper type, you'd access the property specific
, which will do an extra database request behind the scenes to fill in the missing detail.
(Note that this doesn't apply when you run a query that explicitly asks for a specific type of page: with a query like Event.objects.sibling_of(self)
, we know we'll be getting Event
pages back, so we don't need to call specific
on the results.)
So, if isinstance(parent_page, Event):
wouldn't work - it'll always be false, because at that point parent_page
is a basic Page
object (regardless of whether the page is really an Event
or an EventIndex
).
if isinstance(parent_page.specific, Event):
would work, but it's a little bit inefficient, because in the case that parent_page
is the event index page, you're firing off an extra database request that you don't really need. A better alternative is to use parent_page.specific_class
, which tells you the specific type of the page without firing off that extra database request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With