Wagtail - how to (correctly) get other pages/models

Viewed 275

Using Wagtail which is the more appropriate way of getting the records of other pages/models.

# models.py

def get_context(self, request, *args, **kwargs):
    context = super().get_context(request, *args, **kwargs)
    context['children'] = ArticleDetailPage.objects.live().public()[:3]
    return context
# template.html

{% for item in children %}
    <li>{{ item }}</li>
{% endfor %}

Or,

# models.py

def articles(self):
    articles = ArticleDetailPage.objects.live().public()[:3]
    return articles
# template.html

{% for item in page.articles %}
    <li>{{ item }}</li>
{% endfor %}

Both of these methods work and I see the former often used in the docs and either one used elsewhere. Is there a difference at all to which one is used in terms of performance or "correctness" or is it simply personal preference?

1 Answers

AFAIW, it's just personal preference. The first one is more explicit, the second one keeps your context more clean. The only difference I can think of is that in the second option ArticleDetailPage.objects.live().public()[:3] is only called when you actually include {{page.articles}} in your template, which could lead to a tiny boost in performance if the query is quite complex.

In general I tend to wrap these kind of variables in a property when either:

  1. I know there is an explicit relationship there. So in this case, when they're subpages of the page rendering the template. A variable like shopping_cart or breadcrumb would be less likely to be coupled to the page itself.

or

  1. The variable is used in other parts of my Django/Wagtail code apart from the template. It's very much possible that I want to access the articles of a page from somewhere else.

Otherwise, I just pass it directly in the context.

Related