Django

How to use managers in Django

The communication with the database and the abstraction about the database’s engine we are using is one of the best features of Django. All of this is thanks to the Managers, an interface between database and Django models.

All models in Django have at least one manager. By default, the models use django.db.models.manager. Manager like manager class default, which it’s assigned to objects field in the model.

Usually, the custom managers are used for two reasons:

  • Complex and reusable filters. If it’s necessary to create a complex or reusable filter, you can develop your own manager with a method that makes this work.
    # models.py
    class Book(models.Model):
       title = models.CharField(_('Title'), null=False, blank=False, max_length=256)
       pub_date = models.DateField()
       objects = MyCustomManager()
    
    # managers.py
    class MyCustomManager(models.Manager):
       def my_filter(date, contained_title):
           return super(MyCustomManager, self).get_queryset().exclude(pub_date__gt=date, title__icontains=contained_title).order_by('-pub_date', 'title')

With this code, Book.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), title__icontains='Hello').order_by('-pub_date', 'title') returns the same data as Book.objects.my_filter(datetime.date(2005, 1, 3),'Hello'). With this functionality we avoid errors when we are writing a very long filter.

  • Modify the queryset. In Django, the model’s queryset is a complete or partial instances model list. We can save time by developing a custom manager that works with a filtered queryset.

Example:

If we have stored in database 10 objects of the model ‘Article’ (7 of them created in 2015 and the rest created before), we can develop a custom manager that works only with the articles created since 2015. In this case, Article.since_2015.all() would return 7 objects, all created from 2015 onwards. Also, we can keep using the different functions that a manager provides: Article.since_2015.get(), Article.since_2015.filter(), etc.

Also, we can define a manager through a custom QuerySet class as follows:

custom_manager = MyCustomQuerySet.as_manager()

Can we use more than one manager?

Django offers the possibility of using as many managers as we want, but only one is used as default. It is not advisable to use as default manager a custom manager that modifies the queryset. This would cause errors with related models, migrations, dumpdata, etc.

When we define a model, the first manager founded in the model’s fields will be selected as default manager. On the other hand, we can choose manually what manager will be the default manager defining the variable ‘default_manager_name’ in the Meta of our model.

Custom manager inheritance

Since Django 1.10, the models can inherit all managers from their parent classes, even if the parent class is abstract. The inheritance procedure works as follow:

  1. All managers are inherited
  2. If there is no managers in the parent classes or in the child class, Django provides the default manager (‘objects’) to the child class.
  3. If we aren’t using a custom manager in the child class, the default manager (‘default_manager_name’) will be inherited following the inheritance rules of python. We can clarify this procedure with an example:
class ParentNumberOne(models.Model):
   custom_manager = CustomManager()

class ParentNumberTwo(models.Model):
   another_manager = AnotherManager()

class Child(ParentNumberTwo, ParentNumberOne):
   pass

In this example, the Child’s default_manager_name variable will be ‘another_manager’ because it’s the first manager inherited (Child class inherits everything from the ParentNumberTwo class and later inherits from ParentNumberOne class). If the inheritance would be class Child(ParentNumberOne, ParentNumberTwo):, the ‘default_manager_name’ will be ‘custom_manager’.

Managers in abstract classes

The abstract classes can have managers, but their use it’s only related to the inheritance. The abstract classes haven’t got objects instanced, so the call AbstractClass.objects.all() throws an exception. 

About the author

How to add Social Media buttons to Django admin
02.20.2017

How to add Social Media buttons to Django admin

The Django admin panel is one of the strong points and one of the features we like most, and one of the ways it has as a ...

Why you should use Django for your next website project?
02.14.2017

Why you should use Django for your next website project?

When embarking upon the development of a new web application, one of the most important questions we must ask ourselves is ...

Snippet: Breadcrumbs
12.09.2016

Snippet: Breadcrumbs

The use of breadcrumbs in many of the apps that we develop and maintain is very common. It’s because of that we thought ...

Social Auth in Django
11.22.2016

Social Auth in Django

Today we are going to talk about a library to authenticate with social networks. This library is “python-social-auth” - ...

Let’s have a coffee and talk about your project

START A PROJECT

Let’s have a coffee and talk about your project

START A PROJECT

We use cookies to ensure you get the best experience on our website. More info.

Accept