Python Django ORM - objects.filter() 与 objects.all().filter() - 哪个更受欢迎?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22804252/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:44:26  来源:igfitidea点击:

Django ORM - objects.filter() vs. objects.all().filter() - which one is preferred?

pythondjangodjango-querysetdjango-ormdjango-managers

提问by Dr.Elch

Very often I see constructs like

我经常看到这样的结构

MyModel.objects.all().filter(...)

which will return a QuerySet of the default Mananger. At first all()seems to be quite redundant, because

这将返回默认 Mananger 的 QuerySet。乍一看all()似乎很多余,因为

MyMode.objects.filter(...)

delivers the same result.

提供相同的结果。

However, this seems to be safe for the default Manager only, because of the following two statements in the Django documentation:

但是,这似乎仅对默认管理器是安全的,因为 Django 文档中有以下两个语句:

Excerpt from the Chapter "Adding extra manager methods"

摘自“添加额外的管理器方法”一章

A custom Manager method can return anything you want. It doesn't have to return a QuerySet.

自定义 Manager 方法可以返回您想要的任何内容。它不必返回 QuerySet。

Definition of the all()manager method:

all()manager方法的定义:

all() Returns a copy of the current QuerySet (or QuerySet subclass). This can be useful in situations where you might want to pass in either a model manager or a QuerySet and do further filtering on the result. After calling all() on either object, you'll definitely have a QuerySet to work with.

all() 返回当前 QuerySet(或 QuerySet 子类)的副本。这在您可能希望传入模型管理器或 QuerySet 并对结果进行进一步过滤的情况下非常有用。在任一对象上调用 all() 之后,您肯定会有一个 QuerySet 可以使用。

This seems a bit like a contradiction to me. On one hand Django offers the freedom to let a manager method return whatever object type is preferred and on the other hand it requires a QuerySet for the all()method. I'm aware that each manager has a get_querysetmethod which is called by all(). But who stops me from overriding all()in my custom manager? Although I agree it would be bad design to do so.

这对我来说似乎有点矛盾。一方面,Django 提供了让管理器方法返回任何首选对象类型的自由,另一方面,它需要该all()方法的 QuerySet 。我知道每个经理都有一个get_querysetall(). 但是谁阻止我覆盖all()自定义管理器?虽然我同意这样做是糟糕的设计。

  • So as far as I can see, the all()method does not guarantee to return a QuerySet. What exactly does MyModel.objectsreturn? Does this statement call all()? or `get_queryset()?

  • Do you prefer MyModel.objects.filter(...)or MyModel.objects.all().filter(...). And if so, why?

  • Have you ever encountered wonky managers that would mess with those methods in a undesirable way?

  • 所以据我所知,该all()方法不保证返回一个 QuerySet。究竟MyModel.objects返回什么?这个说法叫all()吗?或`get_queryset()?

  • 你喜欢MyModel.objects.filter(...)还是MyModel.objects.all().filter(...). 如果是这样,为什么?

  • 您是否遇到过会以不受欢迎的方式使用这些方法的不稳定经理?

采纳答案by gitaarik

The method all()on a manager just delegates to get_queryset(), as you can see in the Django source code:

all()管理器上的方法只是委托给get_queryset(),正如您在Django 源代码中看到的:

def all(self):
    return self.get_queryset()

So it's just a way to get the QuerySet from the Manager. This can be handy to ensure that you're dealing with a QuerySetand not a Manager, because MyModel.objectsreturns a Manager.

所以这只是一种从 Manager 获取 QuerySet 的方法。这可以方便地确保您处理的是QuerySet而不是Manager,因为MyModel.objects返回一个 Manager。

For example, if you want to iterate over all the items, you can'tdo this:

例如,如果要遍历所有项目,则不能这样做:

for item in MyModel.objects:
    # do something with item

Because you can't iterate over a Manager. However, all()returns the QuerySet, you caniterate over a QuerySet:

因为你不能迭代一个 Manager。但是,all()返回 QuerySet,您可以遍历 QuerySet:

for item in MyModel.objects.all():
    # do something with item

Generally, you should never overwrite all(). You can overwrite get_queryset()but this method mustreturn a QuerySet.

通常,您永远不应该覆盖all(). 您可以覆盖,get_queryset()但此方法必须返回一个 QuerySet。

If you would use a filter method like filter()or exclude(), you would already have the QuerySet, because these methods are proxied to the QuerySet. So you don't have to do something like all().filter().

如果您将使用类似filter()或的过滤器方法exclude(),则您已经拥有 QuerySet,因为这些方法被代理到 QuerySet。所以你不必做类似的事情all().filter()

回答by Bogdan Iulian Bursuc

  1. MyModel.objectsreturns the manager instance. all()return get_query_set(). I think all is there for when you need all objects.
  2. I prefer MyModel.objects.filter()cause the other is just one more method call, and I don't need all objects if I do filter :)
  3. It depends on the purpose. But if they override a base method of the manager, they return the same result format (eg. a QuerySet)
  1. MyModel.objects返回管理器实例。all()返回get_query_set()。我认为当您需要所有对象时,一切都在那里。
  2. 我更喜欢MyModel.objects.filter()因为另一个只是一个方法调用,如果我进行过滤,我不需要所有对象:)
  3. 这取决于目的。但是如果它们覆盖了管理器的基本方法,它们将返回相同的结果格式(例如一个 QuerySet)

回答by aarif faridi

Mymodel.objects.filter(username='abcd')will give list of match record Mymodel.objects.get(pk='abcd')will return single record with matching on primary key value

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