Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

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:

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.

Definition of the all() manager method:

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.

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_queryset method 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.

  • So as far as I can see, the all() method does not guarantee to return a QuerySet. What exactly does MyModel.objects return? 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?

like image 568
Dr.Elch Avatar asked Apr 02 '14 07:04

Dr.Elch


People also ask

What is the purpose of filter () method in Django?

The filter() method is used to filter you search, and allows you to return only the rows that matches the search term.

What is the difference between filter and get method in Django?

Basically use get() when you want to get a single unique object, and filter() when you want to get all objects that match your lookup parameters.

What does Django objects filter return?

Django provides a filter() method which returns a subset of data. It accepts field names as keyword arguments and returns a QuerySet object. As database has only one record where name is 'tom' , the QuerySet object contains only a single record.

Which ORM is used in Django?

One of the most powerful features of Django is its Object-Relational Mapper (ORM), which enables you to interact with your database, like you would with SQL. In fact, Django's ORM is just a pythonical way to create SQL to query and manipulate your database and get results in a pythonic fashion.


1 Answers

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

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 QuerySet and not a Manager, because MyModel.objects returns a Manager.

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

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

Because you can't iterate over a Manager. However, all() returns the QuerySet, you can iterate over a 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 must return a 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().

like image 141
gitaarik Avatar answered Sep 21 '22 22:09

gitaarik