0

I have a home app with HomePage model which gets object from BlogPage model in blog app. I use this code below the obtain the object from BlogPage to HomePage.

blog app

class HomePage(Page):
    primary_header = models.CharField(max_length=100, blank=True,)
    secondary_header = models.CharField(max_length=100, blank=True,)
    hero_banner_image = models.ForeignKey(
        'wagtailimages.Image', 
        null=True,
        blank=False,
        on_delete=models.SET_NULL, 
        related_name='+')

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        # Get object from Blog Page
        blogpages = self.get_children().get(title='Blog Page').get_children().live().public().order_by('-first_published_at')
        context['blogpages'] = blogpages
        return context

I used get() to obtain the object by title, but I feel that it may not be the best way to do it. If I were to rename the BlogPage title field to for example, "The Blog Page", it will break the code since 'Blog Page' is no more used. Is there a better way to queryset from BlogPage to HomePage model?

home app

class BlogPage(Page):
    subpage_types = ['PostPage']

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        category_slug = request.GET.get('category', None)
        context['categories'] = BlogCategory.objects.all()
        return context
Heroo
  • 97
  • 8

1 Answers1

2

If you know that your HomePage will only ever have one child of type BlogPage you can use the Wagtail PageQuerySet exact_type query.

blog_index_page = self.get_children().exact_type(BlogPage).first()
blog_pages = blog_index_page.get_children().live().public().order_by('-first_published_at')

If you are having trouble importing the model from another app, you can work around this with apps.get_model which is part of django.apps.

Note: You may need to do this import within your get_context to avoid circular import issues.

from django.apps import apps

MyModel1 = apps.get_model('app1', 'MyModel1')
LB Ben Johnston
  • 4,751
  • 13
  • 29
  • Thanks alot for the helpful response. When I used your code `blog_pages = self.get_children().exact_type(BlogPage).get_children().live().public().order_by('-first_published_at')`, I got an AttributeError as the `exact_type()` method outputs an object. The `get_children()` is not attribute of an object. So I sliced the first value in the object with this `blog_pages = self.get_children().exact_type(BlogPage)[0].get_children().live().public().order_by('-first_published_at'`. Not sure if thats the right way to do it, but it worked. – Heroo May 06 '20 at 12:33
  • @Heroo - fixed it up based on your comments, what you did is correct, Django will treat slice `[0]` in a similar way to `first()` but `first()` will give you back `None` if no value is found but slide will throw an error. – LB Ben Johnston May 07 '20 at 09:47