2

I am learning class based views in Django. I was reading the Django documentation and read about queryset attribute and the get_queryset() method. When googled them I came across this answer.

I tried to replicate the result using my code:

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

    def get_queryset(self):
        return Question.objects.order_by('-pub_date')[:2]

class IndexView2(generic.ListView):
    template_name = 'polls/index2.html'
    context_object_name = 'latest_question_list2'
    queryset = Question.objects.all()

In answer it is mentioned that 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.

But I was able to insert questions in database and they were available in the page index2.html without restarting, I was able to change the database and changes were reflected on the page index2.html after refreshing the page.

I further googled and found this link. In the DRF website, it is mentioned that queryset will get evaluated once, and those results will be cached for all subsequent requests.

Can you point where I am going wrong ? What link I am missing ?

  • [You will find your answer here](https://stackoverflow.com/questions/19707237/use-get-queryset-method-or-set-queryset-variable#:~:text=When%20you%20set%20queryset%20%2C%20the,is%20called%20for%20every%20request.&text=If%20you%20tried%20to%20do,by%20setting%20queryset%20%2C%20then%20date.) – Imtiaz Ahmed Mar 28 '21 at 15:19

1 Answers1

1

A QuerySet is evaluated once, but the default implementation of get_queryset, will use queryset.all(), thus each time constructing a new queryset that will force reevaluation.

Indeed, the implementation of the .get_queryset(…) method [GitHub] works with:

def get_queryset(self):
    if self.queryset is not None:
        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            queryset = queryset.all()
    elif self.model is not None:
        queryset = self.model._default_manager.all()
    else:
        raise ImproperlyConfigured(
            "%(cls)s is missing a QuerySet. Define "
            "%(cls)s.model, %(cls)s.queryset, or override "
            "%(cls)s.get_queryset()." % {
                'cls': self.__class__.__name__
            }
        )
    ordering = self.get_ordering()
    if ordering:
        if isinstance(ordering, str):
            ordering = (ordering,)
        queryset = queryset.order_by(*ordering)

    return queryset

THis thus means that we each time make a new "copy" of the QuerySet that will be evaluated. In case the queryset is not specified, it will look for the model attribute, and work with the _default_manager for that model.

If you specified an ordering attribute, than that means it will also order the queryset.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555