我经常看到像这样的结构
MyModel.objects.all().filter(...)
这将返回默认Mananger的QuerySet。起初all()
似乎是多余的,因为
MyMode.objects.filter(...)
提供相同的结果。
但是,这对于默认的Manager似乎是安全的,因为Django文档中有以下两个语句:
摘自“添加额外管理器方法”一章
自定义Manager方法可以返回您想要的任何内容。它不必返回QuerySet。
all()
经理方法的定义:
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 source code看到:
def all(self):
return self.get_queryset()
所以这只是从Manager获取QuerySet的一种方法。这可以很方便地确保您处理QuerySet而不是Manager,因为MyModel.objects
返回一个Manager。
例如,如果要迭代所有项目,则无法执行此操作:
for item in MyModel.objects:
# do something with item
因为您无法迭代管理器。但是,all()
返回QuerySet,您可以迭代QuerySet:
for item in MyModel.objects.all():
# do something with item
一般来说,你永远不应该覆盖all()
。您可以覆盖get_queryset()
,但此方法必须返回QuerySet。
如果你使用像filter()
或exclude()
这样的过滤方法,你就已经有了QuerySet,because these methods are proxied to the QuerySet。所以你不必做像all().filter()
这样的事情。
MyModel.objects
返回管理器实例。 all()
返回get_query_set()
。我想当你需要所有物品时,一切都在那里。MyModel.objects.filter()
导致另一个只是一个方法调用,如果我做过滤我不需要所有对象:)Mymodel.objects.filter(username='abcd')
将给出匹配记录列表Mymodel.objects.get(pk='abcd')
将返回单个记录与主键值匹配