django 1.8 官方文件翻譯: 2-3-2 關聯物件參考

weixin_33860722發表於2015-07-24

Django 文件協作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質。

交流群:467338606

網站:http://python.usyiyi.cn/django/index.html

關聯物件參考

class RelatedManager

"關聯管理器"是在一對多或者多對多的關聯上下文中使用的管理器。它存在於下面兩種情況:

ForeignKey關係的“另一邊”。像這樣:

from django.db import models

class Reporter(models.Model):
    # ...
    pass

class Article(models.Model):
    reporter = models.ForeignKey(Reporter)

在上面的例子中,管理器reporter.article_set擁有下面的方法。

ManyToManyField關係的兩邊:

class Topping(models.Model):
    # ...
    pass

class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping)

這個例子中,topping.pizza_set 和pizza.toppings都擁有下面的方法。

add(obj1[, obj2, ...])

把指定的模型物件新增到關聯物件集中。

例如:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.

在上面的例子中,對於ForeignKey關係,e.save()由關聯管理器呼叫,執行更新操作。然而,在多對多關係中使用add()並不會呼叫任何 save()方法,而是由QuerySet.bulk_create()建立關係。如果你需要在關係被建立時執行一些自定義的邏輯,請監聽m2m_changed訊號。

create(**kwargs)

建立一個新的物件,儲存物件,並將它新增到關聯物件集之中。返回新建立的物件:

>>> 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.

這完全等價於(不過更加簡潔於):

>>> 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)

要注意我們並不需要指定模型中用於定義關係的關鍵詞引數。在上面的例子中,我們並沒有傳入blog引數給create()。Django會明白新的 Entry物件blog 應該新增到b中。

remove(obj1[, obj2, ...])

從關聯物件集中移除執行的模型物件:

>>> 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()可會執行更新操作。但是,多對多關係上的remove(),會使用QuerySet.delete()刪除關係,意思是並不會有任何模型呼叫save()方法:如果你想在一個關係被刪除時執行自定義的程式碼,請監聽m2m_changed訊號。

對於ForeignKey物件,這個方法僅在null=True時存在。如果關聯的欄位不能設定為None (NULL),則這個物件在新增到另一個關聯之前不能移除關聯。在上面的例子中,從b.entry_set()移除e等價於讓e.blog = None,由於blog的ForeignKey沒有設定null=True,這個操作是無效的。

對於ForeignKey物件,該方法接受一個bulk引數來控制它如果執行操作。如果為True(預設值),QuerySet.update()會被使用。而如果bulk=False,會在每個單獨的模型例項上呼叫save()方法。這會觸發pre_save和post_save,它們會消耗一定的效能。

clear()

從關聯物件集中移除一切物件。

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()

注意這樣不會刪除物件 —— 只會刪除他們之間的關聯。

就像 remove() 方法一樣,clear()只能在 null=True的ForeignKey上被呼叫,也可以接受bulk關鍵詞引數。

注意

注意對於所有型別的關聯欄位,add()、create()、remove()和clear()都會馬上更新資料庫。換句話說,在關聯的任何一端,都不需要再呼叫save()方法。

同樣,如果你再多對多關係中使用了中間模型,一些關聯管理的方法會被禁用。

直接賦值

通過賦值一個新的可迭代的物件,關聯物件集可以被整體替換掉。

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set = new_list

如果外來鍵關係滿足null=True,關聯管理器會在新增new_list中的內容之前,首先呼叫clear()方法來解除關聯集中一切已存在物件的關聯。否則, new_list中的物件會在已存在的關聯的基礎上被新增。

相關文章