Search code examples
djangoprefetch

Django: Save multiple Prefetch() objects in a variable or method


The documentation displays how to save a Prefetch() object in a variable:

>>> prefetch = Prefetch('choice_set', queryset=voted_choices, to_attr='voted_choices')
>>> Question.objects.prefetch_related(prefetch).get().voted_choices
[<Choice: The sky>]

However, prefetch_related accepts many Prefetch() objects separated with a comma:

>>> Question.objects.prefetch_related(Prefetch('choice_set'), Prefetch('foo')).get().voted_choices

How could this Prefetch() sequence be saved in a variable -or even better in a method- in order to be reusable?


Solution

  • I prefer to add these Prefetch related clauses in a custom QuerySet and then access the created lists through model properties, if they exist.

    usage: Post.objects.filter(...).prefetch_comments()...

    class PostQuerySet(models.QuerySet):
        def prefetch_comments(self):
            inner_qs = Comment.objects.order_by('-date')
            return self.prefetch_related(Prefetch("comments", queryset=inner_qs, to_attr="comments_list"))
    
    
    class Post(models.Model):
        ....
        objects = PostQuerySet.as_manager()
    
        @property
        def most_recent_comment(self):
            if hasattr(self, 'comments_list') and len(self.comments_list) > 0:
                return self.comments_list[0]
            return None