django-model之定義管理器(從數(shù)據(jù)庫查詢數(shù)據(jù)的API)

管理器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()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盆驹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辫封,老刑警劉巖硝枉,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妻味,死亡現(xiàn)場離奇詭異责球,居然都是意外死亡拓劝,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門校套,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牧抵,“玉大人,你說我怎么就攤上這事妹孙』裰Γ” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵嚣崭,是天一觀的道長懦傍。 經(jīng)常有香客問我,道長说榆,這世上最難降的妖魔是什么寸认? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮唱蒸,結(jié)果婚禮上烛愧,老公的妹妹穿的比我還像新娘掂碱。我一直安慰自己疼燥,他們只是感情好蚁堤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撬即,像睡著了一般呈队。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粒竖,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天几于,我揣著相機(jī)與錄音,去河邊找鬼朽砰。 笑死喉刘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饱搏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鬓催!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起宇驾,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤课舍,失蹤者是張志新(化名)和其女友劉穎塌西,沒想到半個月后捡需,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筹淫,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年饰剥,在試婚紗的時候發(fā)現(xiàn)自己被綠了汰蓉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡顾孽,死狀恐怖岩齿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盹沈,我是刑警寧澤吃谣,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站肃晚,受9級特大地震影響仔戈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜监徘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望墓卦。 院中可真熱鬧户敬,春花似錦睁本、人聲如沸忠怖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽问麸。三九已至,卻和暖如春严卖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哮笆。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工稠肘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人项阴。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像略荡,于是被迫代替她去往敵國和親歉胶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容