I'm still getting used to class based views, while I get the general purpose, some things still get past me. I'm following a tutorial which basically walks you through the motions but tends to ignore the fuzzy details, such as this piece of code:
class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView):
"""Generic class-based view listing books on loan to current user."""
model = BookInstance
template_name ='books/bookinstance_list_borrowed_user.html'
paginate_by = 1
def get_queryset(self):
return BookInstance.objects.filter(
borrower=self.request.user
).filter(status__exact='o').order_by('due_back')
I get the model, template_name and paginate_by parts, they're attributes of the ListView class, but what I don't get is the get_queryset part, where is it executed? As seen in the code below it's called nowhere. Where is it returned to? I guess my first question can be chalked down to "What do functions in class based views do?"
{% extends "base_generic.html" %}
{% block content %}
<h1>Borrowed books</h1>
{% if bookinstance_list %}
<ul>
{% for bookinst in bookinstance_list %}
<li class="{% if bookinst.is_overdue %}text-danger{% endif %}">
<a href="{% url 'book-detail' bookinst.book.pk %}">{{bookinst.book.title}}</a> ({{ bookinst.due_back }})
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no books borrowed.</p>
{% endif %}
So, two issues, first, where did the get_queryset return to, and second, what is bookinstance_list? It's not a context variable, but seems to be used out of the blue, why is this variable usable?
Class Based Views calls get_queryset()
in the get()
method of your view, I'll present some example code from Django 1.11.
# django/views/generic/list.py:159
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
...
context = self.get_context_data()
return self.render_to_response(context)
The ListView
class sets self.object_list = self.get_queryset()
in this method, however this doesn't explain where it sets it in the context passed to your template. If we take a quick look at get_context_data()
:
# django/views/generic/list.py:127
def get_context_data(self, **kwargs):
"""
Get the context for this view.
"""
queryset = kwargs.pop('object_list', self.object_list)
page_size = self.get_paginate_by(queryset)
context_object_name = self.get_context_object_name(queryset)
if page_size:
paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
context = {
'paginator': paginator,
'page_obj': page,
'is_paginated': is_paginated,
'object_list': queryset
}
else:
context = {
'paginator': None,
'page_obj': None,
'is_paginated': False,
'object_list': queryset
}
if context_object_name is not None:
context[context_object_name] = queryset
context.update(kwargs)
return super(MultipleObjectMixin, self).get_context_data(**context)
context
is assigned a dictionary with 'object_list': queryset
, so when you're trying to access the resulting QuerySet
from get_queryset
in your template you should access object_list
.
The Django documentation on class-based generic views has a section on extending your context data with additional info. https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-display/#dynamic-filtering
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.