多對多關聯與中介模型
阿新 • • 發佈:2021-06-26
目錄
多對多關聯與中介模型
一 多對多關聯的三種方式
# 多對多關聯關係的建立有三種方式。
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) # 不能用了