Skip to main content
 首页 » 编程设计

python之Django 教程 : What is get_queryset and why "model = poll" isn't needed

2025年05月04日24itcoder

在Django官方教程中,介绍了“通用 View ”。

我们有:

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

(网址:https://docs.djangoproject.com/en/1.6/intro/tutorial04/#amend-views)

它说:

Each generic view needs to know what model it will be acting upon. This is provided using the model attribute.

1/那为什么我们不像在 DetailView 类中那样在 IndexView 类中使用 model = poll 呢?

2/第二个可能相关的问题是:什么是 def get_queryset() 以及我们为什么需要它?难道我们不能做像 queryset = Poll.objects.order_by('-pub_date')[:5] 这样的事情(就像类属性一样)吗?

请您参考如下方法:

这是一个完整的答案,基于文档阅读、测试、此处的答案(感谢 Daniel Roseman 和 knbk,以及一半的猜测(如果我错了请告诉我)。

通用 View 确实需要知道在哪个模型上执行。这是因为通用 View 必须在后台执行查询以检索所需的对象(这将因 View 类型、ListView、DetailView 等而异)。 所以当方法as_view()被调用时,首先调用get_queryset()并返回queryset属性的值。如果未设置后者,则调用模型对象管理器 (poll.objects) 的 all() 方法。

注意:ListView 的 get_queryset() 的文档 isn'nt very clear , 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.

除非它说 all() 方法会在我认为 objects.get(pk=) 会被调用时调用,因为它是“DetailView"而不是 ListView。

最后,正如 knbk 提到的(并在文档中确认),在没有步骤参数的情况下切片时不会评估查询集,这意味着在问题的示例中(= 在 Django 官方教程中),将 queryset = Poll. objects.order_by('-pub_date')[:5] 也可以正常工作(django 1.6 测试)。