Page QuerySet reference

All models that inherit from Page are given some extra QuerySet methods accessible from their .objects attribute.

Examples

Selecting only live pages

live_pages = Page.objects.live()

Selecting published EventPages that are descendants of events_index

events = EventPage.objects.live().descendant_of(events_index)

Getting a list of menu items

# This gets a QuerySet of live children of the homepage with ``show_in_menus`` set
menu_items = homepage.get_children().live().in_menu()

Reference

class wagtail.query.PageQuerySet(*args, **kwargs)
live()

This filters the QuerySet to only contain published pages.

Example:

published_pages = Page.objects.live()
not_live()

This filters the QuerySet to only contain unpublished pages.

Example:

unpublished_pages = Page.objects.not_live()
in_menu()

This filters the QuerySet to only contain pages that are in the menus.

Example:

# Build a menu from live pages that are children of the homepage
menu_items = homepage.get_children().live().in_menu()

Note

To put your page in menus, set the show_in_menus flag to true:

# Add 'my_page' to the menu
my_page.show_in_menus = True
not_in_menu()

This filters the QuerySet to only contain pages that are not in the menus.

in_site(site)

This filters the QuerySet to only contain pages within the specified site.

Example:

# Get all the EventPages in the current site
site = Site.find_for_request(request)
site_events = EventPage.objects.in_site(site)
page(other)

This filters the QuerySet so it only contains the specified page.

Example:

# Append an extra page to a QuerySet
new_queryset = old_queryset | Page.objects.page(page_to_add)
not_page(other)

This filters the QuerySet so it doesn’t contain the specified page.

Example:

# Remove a page from a QuerySet
new_queryset = old_queryset & Page.objects.not_page(page_to_remove)
descendant_of(other, inclusive=False)

This filters the QuerySet to only contain pages that descend from the specified page.

If inclusive is set to True, it will also contain the page itself (instead of just its descendants).

Example:

# Get EventPages that are under the special_events Page
special_events = EventPage.objects.descendant_of(special_events_index)

# Alternative way
special_events = special_events_index.get_descendants()
not_descendant_of(other, inclusive=False)

This filters the QuerySet to not contain any pages that descend from the specified page.

If inclusive is set to True, it will also exclude the specified page.

Example:

# Get EventPages that are not under the archived_events Page
non_archived_events = EventPage.objects.not_descendant_of(archived_events_index)
child_of(other)

This filters the QuerySet to only contain pages that are direct children of the specified page.

Example:

# Get a list of sections
sections = Page.objects.child_of(homepage)

# Alternative way
sections = homepage.get_children()
not_child_of(other)

This filters the QuerySet to not contain any pages that are direct children of the specified page.

ancestor_of(other, inclusive=False)

This filters the QuerySet to only contain pages that are ancestors of the specified page.

If inclusive is set to True, it will also include the specified page.

Example:

# Get the current section
current_section = Page.objects.ancestor_of(current_page).child_of(homepage).first()

# Alternative way
current_section = current_page.get_ancestors().child_of(homepage).first()
not_ancestor_of(other, inclusive=False)

This filters the QuerySet to not contain any pages that are ancestors of the specified page.

If inclusive is set to True, it will also exclude the specified page.

Example:

# Get the other sections
other_sections = Page.objects.not_ancestor_of(current_page).child_of(homepage)
parent_of(other)

This filters the QuerySet to only contain the parent of the specified page.

not_parent_of(other)

This filters the QuerySet to exclude the parent of the specified page.

sibling_of(other, inclusive=True)

This filters the QuerySet to only contain pages that are siblings of the specified page.

By default, inclusive is set to True so it will include the specified page in the results.

If inclusive is set to False, the page will be excluded from the results.

Example:

# Get list of siblings
siblings = Page.objects.sibling_of(current_page)

# Alternative way
siblings = current_page.get_siblings()
not_sibling_of(other, inclusive=True)

This filters the QuerySet to not contain any pages that are siblings of the specified page.

By default, inclusive is set to True so it will exclude the specified page from the results.

If inclusive is set to False, the page will be included in the results.

public()

Filters the QuerySet to only contain pages that are not in a private section and their descendants.

See: Private pages

Note

This doesn’t filter out unpublished pages. If you want to only have published public pages, use .live().public()

Example:

# Find all the pages that are viewable by the public
all_pages = Page.objects.live().public()
not_public()

Filters the QuerySet to only contain pages that are in a private section and their descendants.

private()

Filters the QuerySet to only contain pages that are in a private section and their descendants.

search(query, fields=None, operator=None, order_by_relevance=True, backend='default')

This runs a search query on all the items in the QuerySet

See: Searching QuerySets

Example:

# Search future events
results = EventPage.objects.live().filter(date__gt=timezone.now()).search("Hello")
type(*types)

This filters the QuerySet to only contain pages that are an instance of the specified model(s) (including subclasses).

Example:

# Find all pages that are of type AbstractEmailForm, or one of it's subclasses
form_pages = Page.objects.type(AbstractEmailForm)

# Find all pages that are of type AbstractEmailForm or AbstractEventPage, or one of their subclasses
form_and_event_pages = Page.objects.type(AbstractEmailForm, AbstractEventPage)
not_type(*types)

This filters the QuerySet to exclude any pages which are an instance of the specified model(s).

exact_type(*types)

This filters the QuerySet to only contain pages that are an instance of the specified model(s) (matching the model exactly, not subclasses).

Example:

# Find all pages that are of the exact type EventPage
event_pages = Page.objects.exact_type(EventPage)

# Find all page of the exact type EventPage or NewsPage
news_and_events_pages = Page.objects.exact_type(EventPage, NewsPage)

Note

If you are only interested in pages of a single type, it is clearer (and often more efficient) to use the specific model’s manager to get a queryset. For example:

event_pages = EventPage.objects.all()
not_exact_type(*types)

This filters the QuerySet to exclude any pages which are an instance of the specified model(s) (matching the model exactly, not subclasses).

Example:

# First, find all news and event pages
news_and_events = Page.objects.type(NewsPage, EventPage)

# Now exclude pages with an exact type of EventPage or NewsPage,
# leaving only instance of more 'specialist' types
specialised_news_and_events = news_and_events.not_exact_type(NewsPage, EventPage)
unpublish()

This unpublishes all live pages in the QuerySet.

Example:

# Unpublish current_page and all of its children
Page.objects.descendant_of(current_page, inclusive=True).unpublish()
specific(defer=False)

This efficiently gets all the specific items for the queryset, using the minimum number of queries.

When the “defer” keyword argument is set to True, only generic field values will be loaded and all specific fields will be deferred.

Example:

# Get the specific instance of all children of the hompage,
# in a minimum number of database queries.
homepage.get_children().specific()

See also: Page.specific

defer_streamfields()

Apply to a queryset to prevent fetching/decoding of StreamField values on evaluation. Useful when working with potentially large numbers of results, where StreamField values are unlikely to be needed. For example, when generating a sitemap or a long list of page links.

Example:

# Apply to a queryset to avoid fetching StreamField values
# for a specific model
EventPage.objects.all().defer_streamfields()

# Or combine with specific() to avoid fetching StreamField
# values for all models
homepage.get_children().defer_streamfields().specific()
first_common_ancestor(include_self=False, strict=False)

Find the first ancestor that all pages in this queryset have in common. For example, consider a page hierarchy like:

- Home/
    - Foo Event Index/
        - Foo Event Page 1/
        - Foo Event Page 2/
    - Bar Event Index/
        - Bar Event Page 1/
        - Bar Event Page 2/

The common ancestors for some queries would be:

>>> Page.objects\
...     .type(EventPage)\
...     .first_common_ancestor()
<Page: Home>
>>> Page.objects\
...     .type(EventPage)\
...     .filter(title__contains='Foo')\
...     .first_common_ancestor()
<Page: Foo Event Index>

This method tries to be efficient, but if you have millions of pages scattered across your page tree, it will be slow.

If include_self is True, the ancestor can be one of the pages in the queryset:

>>> Page.objects\
...     .filter(title__contains='Foo')\
...     .first_common_ancestor()
<Page: Foo Event Index>
>>> Page.objects\
...     .filter(title__exact='Bar Event Index')\
...     .first_common_ancestor()
<Page: Bar Event Index>

A few invalid cases exist: when the queryset is empty, when the root Page is in the queryset and include_self is False, and when there are multiple page trees with no common root (a case Wagtail does not support). If strict is False (the default), then the first root node is returned in these cases. If strict is True, then a ObjectDoesNotExist is raised.

Overrides Django’s native select_related() to allow related objects to be fetched by the subqueries made when a specific queryset is evaluated.

When for_specific_subqueries is False (the default), the method functions exactly like the original method. However, when True, fields are required, and must match names of ForeignKey fields on all specific models that might be included in the result (which can include fields inherited from concrete parents). Unlike when for_specific_subqueries is False, no validation is applied to fields when the method is called. Rather, that when the method is called. Instead, that validation is applied for each individual subquery when the queryset is evaluated. This difference in behaviour should be taken into account when experimenting with for_specific_subqueries=True .

As with Django’s native implementation, you chain multiple applications of select_related() with for_specific_subqueries=True to progressively add to the list of fields to be fetched. For example:

# Fetch 'author' when retrieving specific page data
queryset = Page.objects.specific().select_related("author", for_specific_subqueries=True)

# We're rendering cards with images, so fetch the listing image too
queryset = queryset.select_related("listing_image", for_specific_subqueries=True)

# Fetch some key taxonomy data too
queryset = queryset.select_related("topic", "target_audience", for_specific_subqueries=True)

As with Django’s native implementation, None can be supplied in place of fields to negate a previous application of select_related(). By default, this will only work for cases where select_related() was called without for_specific_subqueries, or with for_specific_subqueries=False. However, you can use for_specific_subqueries=True to negate subquery-specific applications too. For example:

# Fetch 'author' and 'listing_image' when retrieving specific page data
queryset = Page.objects.specific().select_related(
    "author",
    "listing_image",
    for_specific_subqueries=True
)

# I've changed my mind. Do not fetch any additional data
queryset = queryset.select_related(None, for_specific_subqueries=True)

Overrides Django’s native prefetch_related() implementation to allow related objects to be fetched alongside the subqueries made when a specific queryset is evaluated.

When for_specific_subqueries is False (the default), the method functions exactly like the original method. However, when True, lookups are required, and must match names of related fields on all specific models that might be included in the result (which can include relationships inherited from concrete parents). Unlike when for_specific_subqueries is False, no validation is applied to lookups when the method is called. Instead, that validation is applied for each individual subquery when the queryset is evaluated. This difference in behaviour should be taken into account when experimenting with for_specific_subqueries=True.

As with Django’s native implementation, you chain multiple applications of prefetch_related() with for_specific_subqueries=True to progressively add to the list of lookups to be made. For example:

# Fetch 'contributors' when retrieving specific page data
queryset = Page.objects.specific().prefetch_related("contributors", for_specific_subqueries=True)

# We're rendering cards with images, so prefetch listing image renditions too
queryset = queryset.prefetch_related("listing_image__renditions", for_specific_subqueries=True)

# Fetch some key taxonomy data also
queryset = queryset.prefetch_related("tags", for_specific_subqueries=True)

As with Django’s native implementation, None can be supplied in place of lookups to negate a previous application of prefetch_related(). By default, this will only work for cases where prefetch_related() was called without for_specific_subqueries, or with for_specific_subqueries=False. However, you can use for_specific_subqueries=True to negate subquery-specific applications too. For example:

# Fetch 'contributors' and 'listing_image' renditions when retrieving specific page data
queryset = Page.objects.specific().prefetch_related(
    "contributors",
    "listing_image__renditions",
    for_specific_subqueries=True
)

# I've changed my mind. Do not make any additional queries
queryset = queryset.prefetch_related(None, for_specific_subqueries=True)

#### Performance considerations

Typical usage of prefetch_related() results in an additional database query being executed for each of the provided lookups. However, when combined with for_specific_subqueries=True, this additional number of database queries is multiplied for each specific type in the result. If you are only fetching a small number of objects, or the type-variance of results is likely to be high, the additional overhead of making these additional queries could actually have a negative impact on performance.

Using prefetch_related() with for_specific_subqueries=True should be reserved for cases where a large number of results is needed, or the type-variance is retricted in some way. For example, when rendering a list of child pages where allow_subtypes is set on the parent, limiting the results to a small number of page types. Or, where the type() or not_type() filters have been applied to restrict the queryset to a small number of specific types.