使用 get_queryset() 方法或设置查询集变量?
Posted
技术标签:
【中文标题】使用 get_queryset() 方法或设置查询集变量?【英文标题】:Use get_queryset() method or set queryset variable? 【发布时间】:2013-11-11 12:01:57 【问题描述】:这两段代码乍一看是相同的:
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_poll_list'
queryset = Poll.active.order_by('-pub_date')[:5]
和
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]
它们之间有什么区别吗?如果是:
什么方法更好?或者当设置queryset
变量优于覆盖get_queryset
方法时?反之亦然。
【问题讨论】:
【参考方案1】:在您的示例中,覆盖 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]
get_queryset
有用的另一个示例是当您想要基于可调用对象进行过滤时,例如,返回今天的民意调查:
class IndexView(generic.ListView):
def get_queryset(self):
"""Returns Polls that were created today"""
return Poll.active.filter(pub_date=date.today())
如果您尝试通过设置queryset
来做同样的事情,那么date.today()
只会在视图加载时被调用一次,并且视图会在一段时间后显示不正确的结果。
class IndexView(generic.ListView):
# don't do this!
queryset = Poll.active.filter(pub_date=date.today())
【讨论】:
你也可以写get_queryset
self.model.objects.filter(...)
。在继承自己的列表视图的情况下,值得记住的是应该参考super(YourListViewExtendingSomeOtherLV, self).get_queryset().filter(...)
【参考方案2】:
其他答案忽略了一个重要含义,即在进程启动时评估 queryset
属性这一事实。因为您不只是创建一个查询集,您实际上是在对其进行切片,此时查询将被求值。这意味着您此时只会获得前 5 名民意调查,即使您创建另一个民意调查,它们也不会刷新,直到流程重新启动。
这正是你应该使用get_queryset()
的时候。
【讨论】:
根据the docs,切片未评估的查询集不会导致它被评估,除非您使用切片语法的'step'参数。 这不是真的,如果你在数据库中插入了一个新的最近条目,它就会出现。我刚刚测试过,自己测试一下。例如,如果查询集限制在 timezone.now() 之前,那么是的,在程序启动之后,您将永远不会得到任何结果(除非程序重新启动)。查询是根据请求运行的,但查询中的任何术语(例如 timezone.now() 都不会重新评估,而是初始值)。【参考方案3】:queryset 属性在内部使用,始终使用方法(例如,您经常需要根据请求或会话变量执行自定义查询)
【讨论】:
【参考方案4】:模型和查询集非常相似,但查询集的值(如果提供)会覆盖模型的值。
Model 是这个视图显示的对象类型。
覆盖 get_queryset 控制此视图显示的特定实例 (例如:最近创建的 5 个实例)
来自 Django 的文档:
型号:
此视图将为其显示数据的模型。指定 model = Foo 实际上与指定 queryset = Foo.objects.all() 相同,其中 objects 代表 Foo 的默认管理器。
查询集:
表示对象的 QuerySet。 如果提供,则 queryset 的值将取代为模型提供的值。
get_queryset:
get_queryset() 返回将用于检索此视图将显示的对象的查询集。默认情况下,get_queryset() 如果设置了查询集属性的值,则返回它的值,否则通过调用模型属性的默认管理器上的 all() 方法构造一个 QuerySet。
【讨论】:
【参考方案5】:类内只包含
Class MyViewSet(GenericAPIView):
queryset = ''
如果您不在任何地方使用查询集。
这对我有用。
谢谢
【讨论】:
以上是关于使用 get_queryset() 方法或设置查询集变量?的主要内容,如果未能解决你的问题,请参考以下文章
无法在没有 `.queryset` 属性或覆盖 `.get_queryset()` 方法的视图上应用 DjangoModelPermissions
如何在 Django 中覆盖“get_queryset()”
如何将值从 get_queryset() 传递到 get_context_data()
Django get_object ,get_queryset方法