A Manager is used to query database operations which will be provided to Django models. Every model in Django application consists at least one Manager by default.
By default, Django adds a Manager with the name "objects" to every Django model class. However, if you want to use "objects" as a field name (or) if you want to use a name instead of "objects" for the Manager, you can rename it on a per-model basis. To rename the Manager for a given class, define a class attribute of type models.Manager() on that model.
from django.db import models class Employee(models.Model): gender_choices = ( ("M", "Male"), ("F", "Female") ) roles_choices = ( ("J", "Junior"), ("S", "Senior"), ) first_name = models.CharField(max_length=200) last_name = models.CharField(max_length=200) email = models.CharField(max_length=250) gender = models.CharField(max_length=1, choices=gender_choices) role = models.CharField(max_length=120, choices=roles_choices, default="J") active = models.BooleanField(default=True) # custom manager replaces objects manger all_employees = models.Manager() def __str__(self): return str(self.first_name) + str(self.last_name)
Using the above example model, Employee.objects will throw you an AttributeError exception, but Employee.all_employees.all() will provide a list of all Employee objects.
Now, here we go for the Custom Managers:
You can use a custom Manager in a particular model by extending the base Manager class and instantiating your custom Manager in your model.
There are two reasons you might want to customize a Manager: to add extra Manager methods, and/or to modify the initial QuerySet the Manager returns.
Note: Manager methods can access self.model to get the model class to which they’re attached.
Here I'm gonna explain Modifying a manager’s initial QuerySet for now:
A Manager’s base QuerySet returns all objects in the system. For example, from the above example using Employee model (except the Custom Manager name):
the statement Employee.objects.all() will return all employees in the database.
You can override a Manager’s base QuerySet by overriding the Manager.get_queryset() method. get_queryset() should return a QuerySet with the properties you require.
For example, the following model has two Managers – one that returns all objects, and one that returns only the active employees:
# First, define the Manager subclass. class EmployeeManager(models.Manager): def get_queryset(self): return super(EmployeeManager, self).get_queryset().filter(active=True) # Then hook it into the Employee model explicitly. class Employee(models.Model): ..... active = models.BooleanField(default=True) objects = models.Manager() # The default manager. active_objects = EmployeeManager() # The EmployeeManager manager.
With this sample model, Employee.objects.all() will return all employees in the database, but Employee.active_objects.all() will only return the ones who are in active state.
Of course, because get_queryset() returns a QuerySet object, you can use filter(), exclude() and all the other QuerySet methods on it. So these statements are all legal:
Employee.active_objects.all() Employee.active_objects.filter(email@example.com') Employee.active_objects.count()
This example also pointed out another interesting technique: using multiple managers on the same model. You can attach as many Manager() instances to a model as you’d like. This is an easy way to define common “filters” for your models.
class SeniorManager(models.Manager): def get_queryset(self): return super(SeniorManager, self).get_queryset().filter(role='S') class JuniorManager(models.Manager): def get_queryset(self): return super(JuniorManager, self).get_queryset().filter(role='J') class Employee(models.Model): ... roles_choices = ( ("J", "Junior"), ("S", "Senior"), ) .... role = models.CharField(max_length=1, choices=role_choices) all_employees = models.Manager() seniors = SeniorManager() juniors = JuniorManager()
This example allows you to request Employee.all_employees.all(), Employee.seniors.all() and Employee.juniors.all() yielding predictable results.
While most methods from the standard QuerySet are accessible directly from the Manager, this is only the case for the extra methods defined on a custom QuerySet if you also implement them on the Manager:
class EmployeeQuerySet(models.QuerySet): def juniors(self): return self.filter(role='J') def seniors(self): return self.filter(role='S') class EmployeeManager(models.Manager): def get_queryset(self): return EmployeeQuerySet(self.model, using=self._db) def juniors(self): return self.get_queryset().juniors() def seniors(self): return self.get_queryset().seniors() class Employee(models.Model): ... roles_choices = ( ("J", "Junior"), ("S", "Senior"), ) .... role = models.CharField(max_length=1, choices=role_choices) all_employees = EmployeeManager()
This example allows you to call both juniors() and seniors() directly from the manager Employee.all_employees.
Micropyramid is a software development and cloud consulting partner for enterprise businesses across the world. We work on python, Django, Salesforce, Angular, Reactjs, React Native, MySQL, PostgreSQL, Docker, Linux, Ansible, git, amazon web services. We are Amazon and salesforce consulting partner with 5 years of cloud architect experience. We develop e-commerce, retail, banking, machine learning, CMS, CRM web and mobile applications.
Django-CRM :Customer relationship management based on Django
Django-blog-it : django blog with complete customization and ready to use with one click installer Edit
Django-webpacker : A django compressor tool
Django-MFA : Multi Factor Authentication
Docker-box : Web Interface to manage full blown docker containers and imagesMore...