【问题标题】:Context value seems not passed into ListView in Django?上下文值似乎没有传递到 Django 中的 ListView?
【发布时间】:2015-06-06 05:46:38
【问题描述】:

我正在学习https://docs.djangoproject.com/en/1.7/intro/tutorial04/ 中的 Django 1.7 教程。 我从网上复制代码,然后运行它。我遇到两个问题:

  1. 添加继承ListView的IndexView后,127.0.0.1:8000/polls页面只返回“No polls are available”。没有任何数据库项目。我对基于分类的视图感到困惑,似乎上下文值没有传递给模板。 ---------> 解决了,这是我的愚蠢类型错误。
  2. get_queryset(),是干什么用的,当这个方法被调用时,这个是如何映射到上下文的?这个函数怎么知道上下文映射,如果有两个上下文和两个值呢?

有人可以在这里给我一些指导吗?非常感谢。

投票/urls.py

    from django.conf.urls import patterns, url

    from . import views

    urlpatterns = patterns('',
        url(r'^$', views.IndexView.as_view(), name='index'),
        #url(r'^$', views.index, name='index'),  #this url works
        url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
        url(r'^(?P<pk>\d+)/results/$', views.ResultsView.as_view(), name='results'),
        url(r'^(?P<question_id>\d+)/vote/$', views.vote, name='vote'),
    )

polls/views.py

    from django.http import HttpResponse, Http404,HttpResponseRedirect
    from django.template import RequestContext, loader
    from django.shortcuts import render,get_object_or_404
    from .models import Question, Choice
    from django.core.urlresolvers import reverse

    from django.views import generic


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

        def get_queryset(self):
            return Question.objects.order_by('-pub_date')[:5]
    #this works
    #def index(request):     
    #    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    #    context = {'latest_question_list': latest_question_list}
    #   return render(request, 'polls/index.html', context)

民意调查/index.html

        {% if latest_question_list %}    <!-- seems here value is not passed by -->
            <ul>
            {% for question in latest_question_list %}
                <li>
                    {{ question.question_text }}</li>
            {% endfor %}
            </ul>
        {% else %}
            <p>{{ latest_question_list }}</p>
            <p>No polls are available.</p>    <!-- always display this -->
            <p>{{ latest_question_list }}</p>
        {% endif %}

数据库

>>> from polls.models import Question
>>> Question.objects.all()
[<Question: What's up?>, <Question: tttt>]

【问题讨论】:

  • 请注意,context_object_name'last_question_list',但在模板中您正在检查 'latest_question_list'
  • 是的,解决了。真是愚蠢的错误。但是 last_question_list 仍然是如何映射到上下文的?我猜是通过 get_queryset(),但是 Question.objects.order_by('-pub_date')[:5] 是如何自动链接到 last_question_list 的。

标签: python django


【解决方案1】:

由于 Django 是开源的,因此可以通过 context_object_name 变量确定 queryset 如何在模板中可用。我们来看看django.views.generic.list.py

class MultipleObjectMixin(ContextMixin):
    # Some fields
    context_object_name = None

    def get_queryset(self):
        # get_queryset implementation

    def get_context_object_name(self, object_list):
        """
        Get the name of the item to be used in the context.
        """
        if self.context_object_name:
            return self.context_object_name
        elif hasattr(object_list, 'model'):
            return '%s_list' % object_list.model._meta.model_name
        else:
            return None

    def get_context_data(self, **kwargs):
        queryset = kwargs.pop('object_list', self.object_list)
        # Some stuff
        context_object_name = self.get_context_object_name(queryset)
        # Some other stuff
        if context_object_name is not None:
            context[context_object_name] = queryset
        context.update(kwargs)
        return super(MultipleObjectMixin, self).get_context_data(**context)

    # And, of course, a lot of other functions


class BaseListView(MultipleObjectMixin, View):
    def get(self, request, *args, **kwargs):
        self.object_list = self.get_queryset()
        # Some magic
        context = self.get_context_data()
        return self.render_to_response(context)

    # Skipped

当你调用get 方法时,Django 用get_queryset() 初始化self.object_list。然后,它调用get_context_data() 并将上下文数据传递给模板。

MultipleObjectMixin.get_context_data 返回带有 name-&gt;variable 对的字典。它会创建一对get_context_object_name() -> object_list,这就是为什么您可以使用定义的context_object_name 名称访问您的列表。

【讨论】:

    【解决方案2】:

    基于类的视图通过提供大量预烘焙代码使开发人员的任务变得更加容易。 ListView 用于返回对象列表。 ListView 像所有其他视图一样是从View 扩展而来的。 View 实现了一个 get_context_data 方法,该方法传递要在模板中使用的数据。所以,现在如果检查 ListView 的get_context_data 方法,我们会发现:

    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)
    

    如您所见,object_list 被设置为 queryset,或者如果您提供 context_object_name,它被设置为 queryset。并且查询集由您定义的get_queryset 设置。

    我希望这可以使过程清晰。

    【讨论】:

      猜你喜欢
      • 2016-08-01
      • 2015-04-19
      • 1970-01-01
      • 2013-06-04
      • 1970-01-01
      • 1970-01-01
      • 2022-06-24
      • 2019-11-25
      • 1970-01-01
      相关资源
      最近更新 更多