django

django-model之定义管理器(从数据库查询数据的API)

2018-08-22  本文已影响14人  陆_志东

管理器Manager

管理器是Django 的模型进行数据库查询操作的接口。Django 应用的每个模型都拥有至少一个管理器

管理器的名字 objects

默认情况下,Django 为每个模型类添加一个名为objects的管理器

如果你不想使用objects,而是自定义

如果你想将objects用于字段名称,或者你想使用其它名称而不是objects访问管理器
在模型中定义一个值为models.Manager()的属性,来重命名管理器。例如:

from django.db import models

class Person(models.Model):
    #...
    people = models.Manager()  # 这样就把管理器objects修改为了people


# 使用
之前是Person.objects.all()
现在是Person.people.all()会返回一个包含所有Person对象的列表。

修改管理器的原因:

你有两个原因可能会自己定义管理器:1.向管理器类中添加额外的方法 2.修改管理器返回的原始查询集。

一: 向管理器类中添加额外的方法

例如,下面这个自定义管理器提供一个with_counts() 方法,它返回所有OpinionPoll 对象的列表,列表的每项都有一额外num_responses 属性,该属性保存一个聚合查询的结果(注:对应的应是SQL查询语句中的COUNT(*)生成的项):
在该例中,你可以使用OpinionPoll.objects.with_counts() 返回带有num_responses 属性的OpinionPoll 对象列表。注意是对象列表

from django.db import models

class PollManager(models.Manager):
    def with_counts(self):
        from django.db import connection
        cursor = connection.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])
            # 管理器方法可以通过self.model 来得到它所属的模型类。
            # 这里相当于创建了很多OpinionPoll类的实例,然后添加到列表里面,这也正符合django的查询集返回格式
            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)
    person_name = models.CharField(max_length=50)
    response = models.TextField()

二:修改管理器的原始查询集

管理器自带的 查询集返回系统中所有的对象。例如,使用下面这个模型:

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)
# Book.objects.all() 语句将返回数据库中所有的 Book 对象。

修改返回的查询集,也就是在查询集之后做一些操作
方法:
通过重写Manager.get_queryset() 方法来覆盖管理器自带的Queryset , get_queryset() 会根据你所需要的属性返回查询集。
例如,下面的模型有两个管理器,一个返回所有的对象,另一个则只返回作者是Roald Dahl 的对象:

# First, define the Manager subclass.
class DahlBookManager(models.Manager):
    def get_queryset(self):
        return super(DahlBookManager, self).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.

Book.objects.all()将返回数据库中所有的图书
Book.dahl_objects.all() 只返回作者是 Roald Dahl 的图书。

同时定义多个管理器,

该例还展示了另外一个很有意思的技巧:同一模型使用多个管理器。你可以依据你自己的偏好在一个模型里面添加多个 Manager() 实例。这是给模型添加通用过滤器(选择器)的一个简单方法:

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

class EditorManager(models.Manager):
    def get_queryset(self):
        return super(EditorManager, self).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()
上一篇 下一篇

猜你喜欢

热点阅读