Django ORM-objects.filter()vs.objects.all()。filter()-哪个是首选?
我经常看到类似的构造
MyModel.objects.all().filter(...)
这将返回默认Mananger的QuerySet。起初all()
似乎很多余,因为
MyMode.objects.filter(...)
提供相同的结果。
但是,由于Django文档中的以下两个语句,这似乎仅对默认管理器是安全的:
摘自“添加额外的管理器方法”一章
自定义Manager方法可以返回您想要的任何内容。它不必返回QuerySet。
all()
manager方法的定义:
all()返回当前QuerySet(或QuerySet子类)的副本。在您可能想要传入模型管理器或QuerySet并对结果进行进一步过滤的情况下,这很有用。在任一对象上调用all()之后,您肯定会有一个QuerySet可以使用。
对我来说,这似乎有点矛盾。一方面,Django提供了让管理器方法返回首选对象类型的自由,另一方面,它需要该all()
方法的QuerySet
。我知道每个管理器都有一个get_queryset
由调用的方法all()
。但是谁阻止我all()
在我的自定义经理中压倒一切呢?尽管我同意这样做是不好的设计。
-
据我所知,该
all()
方法不能保证返回QuerySet。究竟MyModel.objects
返回什么?此语句调用all()
吗?或`get_queryset()? -
您喜欢
MyModel.objects.filter(...)
还是MyModel.objects.all().filter(...)
。如果是这样,为什么? -
您有没有遇到过会以不希望的方式弄乱那些方法的笨拙的经理?
-
all()
经理的方法只是委托给get_queryset()
,如Django源代码所示:def all(self): return self.get_queryset()
因此,这只是从Manager中获取QuerySet的一种方法。确保返回的是Manager,这对于确保您正在处理QuerySet而不是Manager是非常方便的
MyModel.objects
。例如,如果要遍历所有项目, 则不能 执行以下操作:
for item in MyModel.objects: # do something with item
因为您无法遍历Manager。但是,
all()
返回QuerySet后,您 可以 遍历QuerySet:for item in MyModel.objects.all(): # do something with item
通常,您绝不应该覆盖
all()
。您可以覆盖,get_queryset()
但是此方法 必须 返回QuerySet。如果您将使用类似
filter()
或的过滤器方法exclude()
,则您将已经拥有QuerySet,因为这些方法被代理到QuerySet。所以您不必做类似的事情all().filter()
。