使用get_queryset()方法或设置queryset变量?

9Al*_*thm 49 django django-views django-generic-views

这两段代码在第一时间是相同的:

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_poll_list'
    queryset = Poll.active.order_by('-pub_date')[:5]
Run Code Online (Sandbox Code Playgroud)

和

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

    def get_queryset(self):
        return Poll.active.order_by('-pub_date')[:5]
Run Code Online (Sandbox Code Playgroud)

它们之间有什么区别吗?如果它是:

什么方法更好?或者当设置queryset变量优于覆盖get_queryset方法时?反之亦然.

Ala*_*air 67

在您的示例中,覆盖queryset并get_queryset具有相同的效果.我会稍微偏爱设置,queryset因为它不那么冗长.

设置queryset时,启动服务器时只创建一次查询集.另一方面,get_queryset为每个请求调用该方法.

这意味着get_queryset如果要动态调整查询,这将非常有用.例如,您可以返回属于当前用户的对象:

class IndexView(generic.ListView):
    def get_queryset(self):
        """Returns Polls that belong to the current user"""
        return Poll.active.filter(user=self.request.user).order_by('-pub_date')[:5]
Run Code Online (Sandbox Code Playgroud)

另一个get_queryset有用的例子是当你想根据可调用进行过滤时,例如,返回今天的民意调查:

class IndexView(generic.ListView):
    def get_queryset(self):
        """Returns Polls that were created today"""
        return Poll.active.filter(pub_date=date.today())
Run Code Online (Sandbox Code Playgroud)

如果您尝试通过设置执行相同的操作queryset,则date.today()只会在加载视图时调用一次,并且视图会在一段时间后显示不正确的结果.

class IndexView(generic.ListView):
    # don't do this!
    queryset = Poll.active.filter(pub_date=date.today())
Run Code Online (Sandbox Code Playgroud)

  • 你也可以在`get_queryset``self.model.objects.filter(...)`中写.在继承自己的列表视图的情况下,值得记住的是,应该引用`super(YourListViewExtendingSomeOtherLV,self).get_queryset().filter(...)` (2认同)

Dan*_*man 9

其他答案错过了queryset在进程启动时评估属性这一事实的重要含义.因为您不仅仅是创建一个查询集,而是实际上正在对它进行切片,因此将在该点评估查询.这意味着您只会在那一刻获得前5名民意调查,即使您创建了另一个民意调查,他们也不会刷新,直到重新启动该流程.

这正是你应该使用的时候get_queryset().

  • 根据[docs](https://docs.djangoproject.com/en/1.8/ref/models/querysets/#when-querysets-are-evaluated),对未评估的查询集进行切片不会导致它被评估,除非您使用切片语法的'step'参数. (2认同)