manager

This is the 16th day of my participation in the August More Text Challenge. For details, see:August is more challenging

Manager is an interface that gives the Django model the ability to manipulate the database. Every model in a Django application has at least one Manager.

1. Name of the manager

Make sure you don’t forget to inherit models.Manager when rewriting

By default, Django adds a Manager named Objects for each model class. However, if you want to use Objects as a field name, or if you want to use a Manager name other than Objects, rename it in the model base class. To rename Manager for the specified class, define a property of type Models.Manager in the model. Such as:

from django.db import models
​
class Person(models.Model) :
    people = models.Manager()
​
>>> "Person. Objects" error (due to redesignation as people)>>> Person.people.all(a)Copy the code

When using this instance model, person.objects generates an AttributeError exception, and person.people.all () returns a list of all Person objects.

2. Custom manager

There are two reasons you might want to customize your Manager:

  • Add extraManagerMethods.
  • Modify theManagerReturned primitiveQuerySet.

2.1. Add additional manager methods

Adding additional Manager methods is generally a better way to add “table level” functionality to the model. (For “row-level” functionality — that is, only manipulating individual model objects through model methods, not custom Manager methods.)

A custom Manager method can return anything; there is no compulsion to return a QuerySet.

# This custom Manager provides a method with_counts() that returns a list of all OpinionPoll objects. Each object has an additional property, num_Response, which is the result of an aggregate query:from django.db import models
​
class PollManager(models.Manager) :
    def with_counts(self) :
        from django.db import connection
        with connection.cursor() as cursor:
            cursor.execute(""" SELECT p.id, p.question, p.poll_date, COUNT(*) FROM polls_opinionpoll p, polls_response r WHERE p.id = r.poll_id GROUP BY p.id, p.question, p.poll_date ORDER BY p.poll_date DESC""")  # Query information
            result_list = []
            for row in cursor.fetchall():
                p = self.model(id=row[0], question=row[1], poll_date=row[2])
                p.num_responses = row[3]
                result_list.append(p)
        return result_list  # No mandatory return of querSetclass OpinionPoll(models.Model) :
    question = models.CharField(max_length=200)
    poll_date = models.DateField()
    objects = PollManager()
​
# call this method and add a NUM_RESPONSES attribute to each object
Copy the code
Opinionpoll.objects.with_counts () returns a list of OpinionPoll objects, each with a NUM_RESPONSES attribute.Copy the code

Pay attention to

It is important to note that the Manager method can get the attached model class from self.model.

Modify the manager’s initial QuerySet

This is for the convenience of reducing the code for the view.py view (no need to write filtering queries in it, and no clutter).Copy the code

Override the get_querySet () method to override the Manager QuerySet. Get_queryset () is where we write the attributes we need.

The following model has two managers: one that returns all objects, and the other that returns only books written in large numbers:

class DahlBookManager(models.Manager) :  Don't forget to inherit models.Manager when rewriting
    def get_queryset(self) :
        return super().get_queryset().filter(author='big strong')
​
class Book(models.Model) :
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)
​
    objects = models.Manager() # The default manager. 
    dahl_objects = DahlBookManager() # The Dahl-specific manager.
Copy the code
>>> Book.objects.all(a)# returns all books in the database
>>> Book.dahl_objects.all(a)Return only books written by Big Strong
Copy the code

Of course, because get_querySet () returns a QuerySet object, you can call filter(), exclude(), and other QuerySet methods on it. So, the following statement is equivalent:

Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()
Copy the code

Multiple managers can be used in a single model. You can add as many managers () as you want to a model. A non-repeating way to define generic “filters” for the model.

3. Default manager (_default_manager)

Using the defined Manager object, note that the first Manager Django encounters (in the order you define it in the model) will have a unique state. The Django class treats the first Manager in the definition as the “default” Manager, and several Components of Django (including DumpData) call the model Manager independently of that model. Therefore, choose the default manager with great care to avoid situations where get_querySet () fails to retrieve the results.

You can specify a custom default manager using Meta. Default_manager_name.Copy the code

4. Base Manager (_base_manager)

When Django accesses the associated object (choice.question), it uses an instance of the Model._base_manager manager class instead of the _default_manager of the associated object. This is because any Djangos that might be retrieved by the default manager will be deleted (and therefore cannot access the associated objects).

5, manager call customQuerySetmethods

QuerySet methods can be accessed directly from the Manager. This instance only applies to the Manager’s additional methods that you define in your custom QuerySet and implement them in:

class PersonQuerySet(models.QuerySet) :
    def authors(self) :
        return self.filter(role='A')
​
class PersonManager(models.Manager) :
    def get_queryset(self) :
        return PersonQuerySet(self.model, using=self._db)
​
    def authors(self) :
        return self.get_queryset().authors()
​
class Person(models.Model) :
    people = PersonManager()
Copy the code

This example allows you to call authors() and editors() directly from the manager person.people.