How to Be a Manager for a Model

Django Custom Managers

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.

Regarding the Manager names:

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.

For example:

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 explainModifying 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='employee@gmail.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.

For example:

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.

Calling custom QuerySet methods from the manager:

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.

How to Be a Manager for a Model

Source: https://micropyramid.com/blog/how-to-add-a-custom-managers-in-django/

0 Response to "How to Be a Manager for a Model"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel