简体   繁体   中英

Django - Where is the context variable?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM