Django - 回顧(2)- 中介模型

1、中介模型

  咱們以前學習圖書管理系統時,設計了Publish、Book、Author、AuthorDetail這樣幾張表,其中Book表和Author表是多對多關係,處理相似這樣簡單的多對多關係時,使用標準的ManyToManyField就能夠了。可是,有時你可能須要關聯數據到兩個模型之間的關係上。python

  例如,有這樣一個應用,它記錄音樂家所屬的音樂小組。咱們能夠用一個ManyToManyField 表示小組和成員之間的多對多關係。可是,有時你可能想知道更多成員關係的細節,好比成員是什麼時候加入小組的。django

  對於這些狀況,Django 容許你指定一箇中介模型來定義多對多關係。 你能夠將其餘字段放在中介模型裏面。原模型的ManyToManyField 字段將使用through 參數指向中介模型。對於上面的音樂小組的例子,代碼以下:學習

from django.db import models

  class Person(models.Model):
      name = models.CharField(max_length=128)

      def __str__(self):  # __unicode__ on Python 2
          return self.name


  class Group(models.Model):
      name = models.CharField(max_length=128)
      members = models.ManyToManyField("Person", through='Membership')

      def __str__(self):  # __unicode__ on Python 2
          return self.name


  class Membership(models.Model):
      person = models.ForeignKey("Person", on_delete=models.CASCADE)
      group = models.ForeignKey("Group", on_delete=models.CASCADE)
      date_joined = models.DateField()
      invite_reason = models.CharField(max_length=64)

 既然你已經設置好ManyToManyField 來使用中介模型(在這個例子中就是Membership),接下來你要開始建立多對多關係。你要作的就是建立中介模型的實例:this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> ringo  =  Person.objects.create(name = "Ringo Starr" )    # 建立一個音樂家ringo
>>> paul  =  Person.objects.create(name = "Paul McCartney" # 建立一個音樂家paul
>>> beatles  =  Group.objects.create(name = "The Beatles" # 建立一個音樂小組beatles
>>> m1  =  Membership(person = ringo, group = beatles,
...     date_joined = date( 1962 8 16 ),
...     invite_reason = "Needed a new drummer." )    # 建立一箇中介模型的實例
>>> m1.save()
>>> beatles.members. all ()   # 多對多的正向查詢語法
[<Person: Ringo Starr>]
>>> ringo.group_set. all ()   # 多對多的反向查詢語法
[<Group: The Beatles>]
>>> m2  =  Membership.objects.create(person = paul, group = beatles,
...     date_joined = date( 1960 8 1 ),
...     invite_reason = "Wanted to form a band." # 建立一箇中介模型的實例
>>> beatles.members. all ()    # 多對多的正向查詢語法
[<Person: Ringo Starr>, <Person: Paul McCartney>]

  注意:與普通的多對多字段不一樣,不能使用add、create和賦值語句(好比,beatles.members = [...])來建立關係:spa

1
2
3
4
5
6
# THIS WILL NOT WORK
>>> beatles.members.add(john)
# NEITHER WILL THIS
>>> beatles.members.create(name = "George Harrison" )
# AND NEITHER WILL THIS
>>> beatles.members  =  [john, paul, ringo, george]

  爲何不能這樣作?這是由於你不能只建立 Person和 Group之間的關聯關係,你還要指定 Membership模型中所須要的全部信息(好比date_joined和invite_reason);而簡單的add、create 和賦值語句是作不到這一點的。因此它們不能在使用中介模型的多對多關係中使用。此時,惟一的辦法就是建立中介模型的實例。設計

  remove()方法被禁用也是出於一樣的緣由。可是clear()方法倒是可用的。它能夠清空某個實例全部的多對多關係:code

1
2
3
4
5
# Beatles have broken up
>>> beatles.members.clear()
# Note that this deletes the intermediate model instances
>>> Membership.objects. all ()
[]
相關文章
相關標籤/搜索