管理器Manager
管理器是Django 的模型進(jìn)行數(shù)據(jù)庫查詢操作的接口。Django 應(yīng)用的每個模型都擁有至少一個管理器
管理器的名字 objects
默認(rèn)情況下阵子,Django 為每個模型類添加一個名為objects的管理器
如果你不想使用objects
,而是自定義
如果你想將objects用于字段名稱挠进,或者你想使用其它名稱而不是objects訪問管理器
在模型中定義一個值為models.Manager()的屬性誊册,來重命名管理器。例如:
from django.db import models
class Person(models.Model):
#...
people = models.Manager() # 這樣就把管理器objects修改為了people
# 使用
之前是Person.objects.all()
現(xiàn)在是Person.people.all()會返回一個包含所有Person對象的列表君旦。
修改管理器的原因:
你有兩個原因可能會自己定義管理器:1.
向管理器類中添加額外的方法 2.
修改管理器返回的原始查詢集于宙。
一: 向管理器類中添加額外的方法
例如悍汛,下面這個自定義管理器提供一個with_counts() 方法,它返回所有OpinionPoll 對象的列表谱俭,列表的每項(xiàng)都有一額外num_responses 屬性,該屬性保存一個聚合查詢的結(jié)果(注:對應(yīng)的應(yīng)是SQL查詢語句中的COUNT(*)生成的項(xiàng)):
在該例中县貌,你可以使用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 來得到它所屬的模型類接谨。
# 這里相當(dāng)于創(chuàng)建了很多OpinionPoll類的實(shí)例,然后添加到列表里面,這也正符合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()
二:修改管理器的原始查詢集
管理器自帶的 查詢集返回系統(tǒng)中所有的對象。例如巷帝,使用下面這個模型:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
# Book.objects.all() 語句將返回數(shù)據(jù)庫中所有的 Book 對象楞泼。
修改返回的查詢集,也就是在查詢集之后做一些操作
方法:
通過重寫Manager.get_queryset() 方法來覆蓋管理器自帶的Queryset , get_queryset() 會根據(jù)你所需要的屬性返回查詢集笤闯。
例如,下面的模型有兩個管理器印蔬,一個返回所有的對象脱衙,另一個則只返回作者是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()將返回數(shù)據(jù)庫中所有的圖書
Book.dahl_objects.all() 只返回作者是 Roald Dahl 的圖書捐韩。
同時定義多個管理器,
該例還展示了另外一個很有意思的技巧:同一模型使用多個管理器鹃锈。你可以依據(jù)你自己的偏好在一個模型里面添加多個 Manager() 實(shí)例。這是給模型添加通用過濾器(選擇器)的一個簡單方法:
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()