Search code examples
djangodjango-viewsdjango-generic-views

Use get_queryset() method or set queryset variable?


These two pieces of code are identical at the first blush:

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_poll_list'
    queryset = Poll.active.order_by('-pub_date')[:5]

and

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_poll_list'

    def get_queryset(self):
        return Poll.active.order_by('-pub_date')[:5]

Is there any difference between them? And if it is:

What approach is better? Or when setting queryset variable is better than override the get_queryset method? And vice versa.


Solution

  • In your example, overriding queryset and get_queryset have the same effect. I would slightly favour setting queryset because it's less verbose.

    When you set queryset, the queryset is created only once, when you start your server. On the other hand, the get_queryset method is called for every request.

    That means that get_queryset is useful if you want to adjust the query dynamically. For example, you could return objects that belong to the current user:

    class IndexView(generic.ListView):
        def get_queryset(self):
            """Returns Polls that belong to the current user"""
            return Poll.active.filter(user=self.request.user).order_by('-pub_date')[:5]
    

    Another example where get_queryset is useful is when you want to filter based on a callable, for example, return today's polls:

    class IndexView(generic.ListView):
        def get_queryset(self):
            """Returns Polls that were created today"""
            return Poll.active.filter(pub_date=date.today())
    

    If you tried to do the same thing by setting queryset, then date.today() would only be called once, when the view was loaded, and the view would display incorrect results after a while.

    class IndexView(generic.ListView):
        # don't do this!
        queryset = Poll.active.filter(pub_date=date.today())