我经常看到像
这样的结构MyModel.objects.all().filter(...)
将返回默认Mananger的QuerySet。起初all()
似乎是多余的,因为
MyMode.objects.filter(...)
提供相同的结果。
但是,这对于默认的Manager似乎是安全的,因为Django文档中有以下两个语句:
摘自章节"添加额外的经理方法"
自定义Manager方法可以返回您想要的任何内容。它没有 返回一个QuerySet。
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(...)
。如果是这样,为什么?
您是否曾遇到过那些会以不合需要的方式搞乱这些方法的经理?
答案 0 :(得分:46)
管理员的方法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()
之类的事情。
答案 1 :(得分:3)
MyModel.objects
返回管理器实例。 all()
返回get_query_set()
。我想当你需要所有物品时,一切都在那里。MyModel.objects.filter()
因为另一个是另外一个方法调用,如果我进行过滤,我不需要所有对象:)答案 2 :(得分:0)
Mymodel.objects.filter(username='abcd')
将给出比赛记录列表
Mymodel.objects.get(pk='abcd')
将返回与主键值匹配的单个记录