class RelatedManager
"關(guān)聯(lián)管理器"是在一對(duì)多或者多對(duì)多的關(guān)聯(lián)上下文中使用的管理器。它存在于下面兩種情況:
ForeignKey關(guān)系的“另一邊”。像這樣:
from django.db import models
class Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter)
在上面的例子中,管理器reporter.article_set擁有下面的方法。
ManyToManyField關(guān)系的兩邊:
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
這個(gè)例子中,topping.pizza_set 和pizza.toppings都擁有下面的方法。
add(obj1[, obj2, ...])
把指定的模型對(duì)象添加到關(guān)聯(lián)對(duì)象集中。
例如:
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.
在上面的例子中,對(duì)于ForeignKey關(guān)系,e.save()由關(guān)聯(lián)管理器調(diào)用,執(zhí)行更新操作。然而,在多對(duì)多關(guān)系中使用add()并不會(huì)調(diào)用任何 save()方法,而是由QuerySet.bulk_create()創(chuàng)建關(guān)系。如果你需要在關(guān)系被創(chuàng)建時(shí)執(zhí)行一些自定義的邏輯,請(qǐng)監(jiān)聽m2m_changed信號(hào)。
create(**kwargs)
創(chuàng)建一個(gè)新的對(duì)象,保存對(duì)象,并將它添加到關(guān)聯(lián)對(duì)象集之中。返回新創(chuàng)建的對(duì)象:
>>> b = Blog.objects.get(id=1)
>>> e = b.entry_set.create(
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... )
# No need to call e.save() at this point -- it's already been saved.
這完全等價(jià)于(不過更加簡(jiǎn)潔于):
>>> b = Blog.objects.get(id=1)
>>> e = Entry(
... blog=b,
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... )
>>> e.save(force_insert=True)
要注意我們并不需要指定模型中用于定義關(guān)系的關(guān)鍵詞參數(shù)。在上面的例子中,我們并沒有傳入blog參數(shù)給create()。Django會(huì)明白新的 Entry對(duì)象blog 應(yīng)該添加到b中。
remove(obj1[, obj2, ...])
從關(guān)聯(lián)對(duì)象集中移除執(zhí)行的模型對(duì)象:
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
和add()相似,上面的例子中,e.save()可會(huì)執(zhí)行更新操作。但是,多對(duì)多關(guān)系上的remove(),會(huì)使用QuerySet.delete()刪除關(guān)系,意思是并不會(huì)有任何模型調(diào)用save()方法:如果你想在一個(gè)關(guān)系被刪除時(shí)執(zhí)行自定義的代碼,請(qǐng)監(jiān)聽m2m_changed信號(hào)。
對(duì)于ForeignKey對(duì)象,這個(gè)方法僅在null=True時(shí)存在。如果關(guān)聯(lián)的字段不能設(shè)置為None (NULL),則這個(gè)對(duì)象在添加到另一個(gè)關(guān)聯(lián)之前不能移除關(guān)聯(lián)。在上面的例子中,從b.entry_set()移除e等價(jià)于讓e.blog = None,由于blog的ForeignKey沒有設(shè)置null=True,這個(gè)操作是無(wú)效的。
對(duì)于ForeignKey對(duì)象,該方法接受一個(gè)bulk參數(shù)來(lái)控制它如果執(zhí)行操作。如果為True(默認(rèn)值),QuerySet.update()會(huì)被使用。而如果bulk=False,會(huì)在每個(gè)單獨(dú)的模型實(shí)例上調(diào)用save()方法。這會(huì)觸發(fā)pre_save和post_save,它們會(huì)消耗一定的性能。
clear()
從關(guān)聯(lián)對(duì)象集中移除一切對(duì)象。
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()
注意這樣不會(huì)刪除對(duì)象 —— 只會(huì)刪除他們之間的關(guān)聯(lián)。
就像 remove() 方法一樣,clear()只能在 null=True的ForeignKey上被調(diào)用,也可以接受bulk關(guān)鍵詞參數(shù)。
注意
注意對(duì)于所有類型的關(guān)聯(lián)字段,add()、create()、remove()和clear()都會(huì)馬上更新數(shù)據(jù)庫(kù)。換句話說(shuō),在關(guān)聯(lián)的任何一端,都不需要再調(diào)用save()方法。
同樣,如果你再多對(duì)多關(guān)系中使用了中間模型,一些關(guān)聯(lián)管理的方法會(huì)被禁用。
通過賦值一個(gè)新的可迭代的對(duì)象,關(guān)聯(lián)對(duì)象集可以被整體替換掉。
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set = new_list
如果外鍵關(guān)系滿足null=True,關(guān)聯(lián)管理器會(huì)在添加new_list中的內(nèi)容之前,首先調(diào)用clear()方法來(lái)解除關(guān)聯(lián)集中一切已存在對(duì)象的關(guān)聯(lián)。否則, new_list中的對(duì)象會(huì)在已存在的關(guān)聯(lián)的基礎(chǔ)上被添加。