假設(shè)我們要記錄樂手和他們所屬的樂隊(duì)万牺。我們可以用一個(gè) ManyToManyField
表示樂手和樂隊(duì)之間的多對多關(guān)系叭披。但是究反,有時(shí)你可能想知道更多成員關(guān)系的細(xì)節(jié)舟奠,比如成員是何時(shí)加入樂隊(duì)的加入樂隊(duì)的原因是什么等。
對于這些情況咐蝇,Django 允許你指定一個(gè)中介模型來定義多對多關(guān)系涯鲁。 你可以將其他字段放在中介模型里面。源模型的 ManyToManyField
字段將使用 through
參數(shù)指向中介模型有序。對于上面的樂隊(duì)的例子抹腿,代碼如下:
from django.db import models
# 樂手
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
# 樂隊(duì)
class Group(models.Model):
name = models.CharField(max_length=128)
# 樂手和樂隊(duì)之間通過中介模型 Membership 來聯(lián)系
members = models.ManyToManyField(Person, through='Membership')
def __str__(self):
return self.name
# 關(guān)系
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
創(chuàng)建樂手和樂隊(duì)對象:
ringo = Person.objects.create(name="Ringo Starr")
paul = Person.objects.create(name="Paul McCartney")
beatles = Group.objects.create(name="The Beatles")
通過中介模型關(guān)聯(lián)樂隊(duì)和樂手:
from datetime import date
m1 = Membership(
person=ringo,
group=beatles,
date_joined=date(1962, 8, 16),
invite_reason="Needed a new drummer."
)
m1.save()
查詢樂隊(duì)和樂手的關(guān)系:
beatles.members.all()
>>> [<Person: Ringo Starr>]
ringo.group_set.all()
>>> [<Group: The Beatles>]
可見,樂隊(duì)和樂手已經(jīng)關(guān)聯(lián)起來旭寿。
使用了中介模型以后警绩,與普通的多對多字段不同,你不能使用 add
盅称、 create
和賦值語句(比如肩祥,beatles.members = [...]
)來創(chuàng)建關(guān)系:
# 不可以使用這些方法
beatles.members.add(john)
beatles.members.create(name="George Harrison")
beatles.members = [john, paul, ringo, george]
remove()
方法同樣不能使用。但是 clear()
方法卻是可用的缩膝。它可以清空某個(gè)實(shí)例所有的多對多關(guān)系:
beatles.members.clear()