Reputation: 2148
In Django Official Tutorial, "Generic views" are introduced.
We have :
(...)
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_poll_list'
def get_queryset(self):
"""Return the last five published polls."""
return Poll.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Poll
template_name = 'polls/detail.html'
(...)
(URL : https://docs.djangoproject.com/en/1.6/intro/tutorial04/#amend-views)
And it says :
Each generic view needs to know what model it will be acting upon. This is provided using the model attribute.
1/ Then why don't we have model = poll
in IndexView class as in DetailView class ?
2/ The second -and maybe related- question is : what is def get_queryset()
and why do we need it? Counldn't we do just do something like queryset = Poll.objects.order_by('-pub_date')[:5]
(just as class atribute)?
Upvotes: 3
Views: 3385
Reputation: 2148
Here's a complete answer, based on documentation reading, testing, answers here (thanks to Daniel Roseman and knbk, and half guessing (so please tell if I'm wrong).
Generic Views indeed need to know upon which model to perform. That is because generic views have to execute a query behind the scenes to retrieve the needed object (which will vary between view types, ListView
, DetailView
etc).
So when the method as_view()
is called, firstly get_queryset()
is called and returns the value of queryset
attribute. If the latter isn't set, the all()
method of the model object manager (poll.objects
) is then called.
Note : While documentation of ListView
's get_queryset()
isn'nt very clear, that of DetailView
seems to confirm the above behavior :
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.
Except it says the all()
method would be called when I rather think objects.get(pk=)
would be, as it's "DetailView
" and not ListView
.
Finally, as knbk mentionned (and confirmed in the docs), querysets aren't evaluated when slicing without a step parameter, which means in the question's example (= in Django official tutorial), putting queryset = Poll.objects.order_by('-pub_date')[:5]
would work just fine as welll (django 1.6 tested).
Upvotes: 3
Reputation: 599778
Because we don't need it if we're overriding get_queryset, since we specify the query directly there.
No, because the [:5] causes the queryset to be evaluated then and there. If we put that in the model definition, then all requests to the view would use the same 5 items: even if new polls were added, they would never appear in the already-evaluated list (until the server is restarted or the process dies).
Upvotes: -1