-->

Use get_queryset() method or set queryset variable

2019-01-30 11:04发布

问题:

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.

回答1:

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())


回答2:

Other answers have missed an important implication of the fact that the queryset attribute is evaluated when the process starts. Because you aren't just creating a queryset, you're actually slicing it, the query will be evaluated at that point. That means that you will only ever get the top 5 polls at that moment, and they won't refresh even if you create another one, until the process is restarted.

This is exactly when you should be using get_queryset().



回答3:

The queryset attribute is used internally, always use the method (you will often have to perform custom queries based on request or session vars for example)



回答4:

Model and queryset are very similar, but queryset's value if provided overrides that of model's.

Model is what type of Object this view displays.

Overriding get_queryset controls what specific instances this view displays (ex: the last 5 instances created)

From Django's documentation:

model:

The model that this view will display data for. Specifying model = Foo is effectively the same as specifying queryset = Foo.objects.all(), where objects stands for Foo’s default manager.

queryset:

A QuerySet that represents the objects. If provided, the value of queryset supersedes the value provided for model.

get_queryset:

get_queryset() Returns the queryset that will be used to retrieve the object that this view will display. By default, get_queryset() returns the value of the queryset attribute if it is set, otherwise it constructs a QuerySet by calling the all() method on the model attribute’s default manager.



回答5:

inside class just include

Class MyViewSet(GenericAPIView):

    queryset = ''

if you don't use the queryset anywhere.

This worked for me.

Thanks