Django ORM-objects.filter()vs.objects.all()。filter()-哪个是首选?

发布于 2021-01-29 15:15:11

我经常看到类似的构造

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

  • 您有没有遇到过会以不希望的方式弄乱那些方法的笨拙的经理?

关注者
0
被浏览
349
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    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()



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看