Django ORM - objects.filter()与objects.all()。filter() - 首选哪一个?

时间:2014-04-02 07:23:36

标签: python django django-queryset django-orm django-managers

我经常看到像

这样的结构
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(...)。如果是这样,为什么?

  • 您是否曾遇到过那些会以不合需要的方式搞乱这些方法的经理?

3 个答案:

答案 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)

  1. MyModel.objects返回管理器实例。 all()返回get_query_set()。我想当你需要所有物品时,一切都在那里。
  2. 我更喜欢MyModel.objects.filter()因为另一个是另外一个方法调用,如果我进行过滤,我不需要所有对象:)
  3. 这取决于目的。但是如果它们覆盖管理器的基本方法,它们将返回相同的结果格式(例如,一个QuerySet)

答案 2 :(得分:0)

Mymodel.objects.filter(username='abcd')将给出比赛记录列表 Mymodel.objects.get(pk='abcd')将返回与主键值匹配的单个记录