Django2.2丨管理器

Manager是一种接口,它赋予了Django模型操作数据库的能力。Django应用中每个模型拥有至少一个Manager。

管理器名称

默认情况下,Django为每个模型类添加一个名为objects的Manager。可以通过自定义重命名Manager。

from django.db import models

class Person(models.Model):
    #...
    people = models.Manager()

Person.people.all()会返回包含所有Person对象的列表。

自定义管理器

继承基类Manager,在模型中实例化自定义Manager,可以在该模型中使用自定义的Manager。也可以添加额外的Manager方法,修改Manager返回的原始QuerySet。

添加额外的管理器方法

添加额外的Manager方法一般是为模型添加“表级”功能的更好方法。(行级功能通过模型方法)

自定义Manager方法能返回任何东西,没有强制必须返回一个QuerySet。

示例

  • 自定义Manager提供一个with_counts(),返回包含所有OpinionPoll对象的列表。并且每个对象都有一个额外属性num_response。
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""")
            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

class OpinionPoll(models.Model):
    question = models.CharField(max_length=200)
    poll_date = models.DateField()
    objects = PollManager()

class Response(models.Model):
    poll = models.ForeignKey(OpinionPoll, on_delete=models.CASCADE)
    person_name = models.CharField(max_length=50)
    response = models.TextField()

修改管理器的初始QuerySet

Manager的基础QuerySet会返回系统中所有的对象。

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)

Book.objects.all()会返回数据库中所有的书。

示例

  • 两个Manager,一个返回所有对象,一个仅返回Roald Dahl写的书
# First, define the Manager subclass.
class DahlBookManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(author='Roald Dahl')

# Then hook it into the Book model explicitly.
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.

get_queryset()返回一个QuerySet对象,可以在上面调用filter()、exclude()和却他QuerySet方法。

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

在一个模型中可以使用多个管理器

class AuthorManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(role='A')

class EditorManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(role='E')

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    role = models.CharField(max_length=1, choices=[('A', _('Author')), ('E', _('Editor'))])
    people = models.Manager()
    authors = AuthorManager()
    editors = EditorManager()

管理器调用自定义QuerySet方法

标准的QuerySet方法能直接从Manager访问。在自定义QuerySet中定义额外的方法,且在Manager中实现。

class PersonQuerySet(models.QuerySet):
    def authors(self):
        return self.filter(role='A')

    def editors(self):
        return self.filter(role='E')

class PersonManager(models.Manager):
    def get_queryset(self):
        return PersonQuerySet(self.model, using=self._db)

    def authors(self):
        return self.get_queryset().authors()

    def editors(self):
        return self.get_queryset().editors()

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    role = models.CharField(max_length=1, choices=[('A', _('Author')), ('E', _('Editor'))])
    people = PersonManager()
©️2020 CSDN 皮肤主题: 点我我会动 设计师:上身试试 返回首页