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