1. 程式人生 > 其它 >多對多關聯與中介模型

多對多關聯與中介模型

目錄

多對多關聯與中介模型

一 多對多關聯的三種方式

# 多對多關聯關係的建立有三種方式。

1 方式一:自行建立第三張表

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()

# 自己建立第三張表,分別通過外來鍵關聯書和作者
class AuthorToBook(models.Model):
    nid = models.AutoField(primary_key=True)
    # 只需要在中間表建立外來鍵關係即可,此表對book和author表不堵車‘一對多’關係中多的一方
    book_id = models.ForeignKey(to=Book, to_field='nid', on_delete=models.CASCADE)
    author_id = models.ForeignKey(to=Author, to_field='nid', on_delete=models.CASCADE)
    date=models.DecimalField()
    class Meta:
        unique_together = ("author", "book")

2 方式二:通過ManyToManyField自動建立第三張表

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    
# 通過ORM自帶的ManyToManyField自動建立第三張表
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()
    # 通過ORM自帶的ManyToManyField自動建立第三張表
    authors=models.ManyToManyField(to='Author')
    def __str__(self):
        return self.name

3 方式三:使用中介模型(自定義中間表)

# 設定ManyTomanyField並指定自行建立的第三張表
class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="書名")

# 自己建立第三張表,並通過ManyToManyField指定關聯
class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="作者姓名")
    books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
    # through_fields接受一個2元組 ('field1', 'field2'):s
    # 其中field1是定義ManyToManyField的模型外來鍵的名(author),field2是關聯目標模型(book)的外來鍵名。

class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")  # 預設的關聯欄位是id
    book = models.ForeignKey(to="Book")

    class Meta:
        unique_together = ("author", "book")

二 中介模型

1 多對多關係中,第三張表的建立
	-預設使用ManyToMany,自動建立
    -使用中介模型
    	-既手動建立第三張表,又可以使用方便的查詢
    -完全自己寫第三張表
    
# 使用中介模型

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE)


class AuthorDatail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)


class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField()

    publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE)
    # 當前在哪個表中,元組中的第一個引數就是 表明_id
    authors=models.ManyToManyField(to='Author',through='AuthorToBook',through_fields=('book_id','author_id'))
    def __str__(self):
        return self.name


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

class AuthorToBook(models.Model):
    nid = models.AutoField(primary_key=True)
    book_id = models.ForeignKey(to=Book, to_field='nid', on_delete=models.CASCADE)
    author_id = models.ForeignKey(to=Author, to_field='nid', on_delete=models.CASCADE)
    date=models.DecimalField()  # 【不能用add ,remove, clear, set等操作的原因,可能會有新的欄位加入,導致資料錯誤】
    
# 使用中介模型後的方法變化:

# 指令碼檔案s1.py  
import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day76.settings")
    import django
    django.setup()
    from app01 import models
    ## (a)不使用中介模型的測試:
    # 東遊記這本書是lqz和egon寫的
    # book=models.Book.objects.get(pk=1)
    # # book.authors.add(1,2) # 自己建立第三張表,不做關聯,用不了了
    # # 只能手動寫
    # models.AuthorToBook.objects.create(book_id_id=1,author_id_id=1)  # 【寫book_id_id的原因:book_id是欄位物件,建表的時候,自動加了_id】
    # models.AuthorToBook.objects.create(book_id_id=1,author_id_id=2)

    # 東遊記這本書所有的作者:原生寫法,不方便
    # book = models.Book.objects.get(pk=1)
    # res=models.AuthorToBook.objects.filter(book_id=book)  ### 【另一種寫法:book_id_id = book.nid】
    # print(res)

    ## (b)使用了中介模型之後: 
    # book = models.Book.objects.get(pk=1)
    # print(book.authors.all())
    	
    # 東遊記這本書是lqz和egon寫的 add ,remove, clear, set
    # 但是連表操作,book.authors這些都能用
    book = models.Book.objects.get(pk=1)
    book.authors.add(1,2) # 不能用了