Built in & Custom Model Managers in Django
Django manager is a class that acts as an interface through which Django models interact with databases. Every model has at least one manager object. It has a lot of methods, attributes to ease working with databases. In fact, many beginner-level Django developers do not know that they use the Manager class object to extract or create desired model object/objects. The default Manager object that Django provides in models is “objects“.
To use the Django default manager object, you have to follow the below syntax –
Here “objects” is the manager object that Django creates by default.
One basic example :
Let’s say we have a model class named Hospital –
class Hospital(models.Model): name = models.CharField(max_length=50) city = models.CharField(max_length=30) def __str__(self): return self.name
But it did not create any objects in the database yet. It only creates an empty table with the structure of hospital objects. To create these objects in the database we need to use our default Django manager object (As we have not to build any custom manager) –
The ‘create’ method creates a new object. It takes field values that the model class wants. In the above code line, we created a hospital object by calling the ‘create’ method which takes field values as an argument.
Giving a custom name to the default manager :
Sometimes there is a need to give a custom name to the default manager. To do this you have to define a class attribute or field of type models.Manager(). Here is an example –
class Student(models.Model): ... students = models.Manager() //now the default manager is named as students
After this, all the operation on the student database table have to be done using the “students” manager –
Student.students.filter(...) // here students manager is used
Any effort of using “objects” as manager for this class will lead to giving an error.
Methods of Manager class :
Manager objects have many in-build methods to ease the operations on the database. Some of the most popular methods are described here –
|all()||returns a query set containing all objects created so far|
|filter(**kwargs)||returns a query set containing a list of objects that match with the given arguments. If no matched object is found, it returns an empty query set.|
|exclude(**kwargs)||it does exactly the opposite of filter() method i.e. returns a queryset containing objects that does not match with given arguments.|
|get(**kwargs)||returns a single object that match with given argument. If multiple objects found it will throw an Model.MultipleObjectsReturned error. If get() doesn’t find any object, it raises a Model.DoesNotExist exception.|
|create(**kwargs)||create a new object with given arguments.|
|order_by(*fields)||sets the ordering of the previously returned queryset according to the arguments passed in it.|
This following example uses python command shell.
>>> h1 = Hospital.objects.create(name="Calcutta Medical",city="kolkata") >>> h2 = Hospital.objects.create(name="dummy",city="Chennai") #creating objects using create() and save all these new objects into database >>> h3 = Hospital.objects.create(name="TATA cancer Hospital",city="Mumbai") >>> h4 = Hospital.objects.create(name="AIIMS Delhi",city="Delhi") >>> h5 = Hospital.objects.create(name='NRS hospital",city="kolkata") ... >>> Hospital.objects.filter(city='kolkata') # returns queryset of objects whose city attribute is 'kolkata' <QuerySet [<Hospital: Calcutta Medical>, <Hospital: NRS hospital>]> >>> Hospital.objects.get(city='Delhi') <Hospital: AIIMS Delhi> >>> Hospital.objects.get(city='kolkata') # raise error as there are multiple objects
These are the most popular methods . However the number of such methods are huge. You can check django documentation for complete reference.
Creating custom managers :
Sometimes you may want django manager to work in a certain way which default manager don’t. In that case you can make your own custom managers. The procedure is easy. You have to make a class which inherits from Manager class. Here is an example –
Let’s talk about Hospital model. We are creating a custom manager called CustomManager which is similar to the default django manager except one thing. When we call all() method of CustomManager object we will not get all objects. Instead we will get all those objects that have city = ‘kolkata’ –
Every manager class have a get_queryset method. It is used to get queryset of objects based on the properties it takes as arguments. If no argument is provided then it will return all the objects. In this example, we create a custom django manager by inheriting Manager class and overriding only the get_queryset method .
So we have defined a custom manager . Now all we have to do is we have to link this manager with Hospital model –
Hospital model have two manager objects. Now if we call Hospital.objects.all() , we get all the hospital objects. But when we call Hospital.kolkata_hospitals.all() we will get only those objects whose city is kolkata.
Note that if you are using multiple manager objects in same model then you need to be careful about the order of the manager objects defined. The first defined manager object will be treated as default manager object. For example – In above example, “objects” is the default manager as it is defined first. Django uses default managers in some internal process. So, be careful about choosing your default manager or you may get some unexpected results. If you want to make a manager default and that manager object is not defined first then you can define it as default manager by setting default_manager_name of Meta class equal to that object name.
class Hospital(models.Models): ... class Meta: default_manager_name = 'kolkata_hospitals' # default manager is now kolkata_hospitals not objects
You can do anything you want with custom managers. You can define a new method to modify some data in database, or return something. It is not necessary that every manager method should return a queryset. In fact you can define methods that return nothing.
If you want to know more , checkout Django’s official documentation on manager – https://docs.djangoproject.com/en/3.0/topics/db/managers/