Django - ORM 多對多關係 - 中間關係表的建立方式探討
阿新 • • 發佈:2018-11-22
目錄
方式二、自動建立第三張表 - MandyToManyField
方式三、半自動建立第三張表 -- 手動建立第三張表+ManyToMany建立關係(推薦使用)
多對多關係 - 三種中間表的建立方式 - 優劣總結
手動建立第三張表(A表,B表,A2B表),A、B內不建立與A2B的關聯關係 -- 增刪改查操作繁雜 不建議使用
自動建立第三張表 -- 刪改查很方便,但是欄位固定,對中間關係表新增欄位難以實現
半自動建立第三張表(手動穿件第三張表(中間關係表),自動建立三表的關係) -- 建議使用
through('A2B表名') :指定手動建立的關係表(A2B)
through_fields('A2B表內當前表關係欄位','A2B表內關係表的欄位'):中介模型
方式一、手動建立第三張表
注意:
- A,B 表內未建立與A2B表的關聯
- 查詢必須通過第三張表進行 ,無法使用基於下劃線的跨表查詢
- 新增操作必須操作三張表,A表新增物件,B表獲取物件,A2B表儲存二者物件
# models內三個表的建立 from django.db import models # Create your models here. class Book(models.Model): # 預設會建立id name = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book2Author(models.Model): id = models.AutoField(primary_key=True) # 手動通過外來鍵關聯欄位 book=models.ForeignKey(to='Book',to_field='id') author=models.ForeignKey(to='Author',to_field='id')
from app01 import models # 查詢紅樓夢這本書所有的作者 全手動 book=models.Book.objects.filter(name='紅樓夢').first() authors=models.Book2Author.objects.filter(book=book).values_list('author_id') print(authors) ll=[i[0] for i in authors] # ll=[1,2] author_list=models.Author.objects.filter(id__in=ll) print(author_list) # 給紅樓夢這本書新增n這個作者 author=models.Author.objects.filter(name='n').first() book = models.Book.objects.filter(name='紅樓夢').first() #去中間表存 ret=models.Book2Author.objects.create(book=book,author=author) # 給紅樓夢這本書,刪除lqz這個作者
方式二、自動建立第三張表 - MandyToManyField
注意:
- related_name 關聯物件反向引用描述符 - 通過book可以引用到Book表中物件
- 只需要操作兩個表在models內
- 以為未在models內操作第三張表,所以後期對第三張表的操作無法新增欄位(可以通過伺服器,但是不推薦)
from django.db import models class Book(models.Model): title = models.CharField(max_length=32, verbose_name="書名") # verbose_name admin中顯示的表名稱 class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") # 通過ORM自帶的ManyToManyField自動建立第三張表 books = models.ManyToManyField(to="Book", related_name="authors") # related_name 關聯物件反向引用描述符 - 通過book可以引用到Book表中物件 # Book.object.filter(name = '紅樓夢').authors.all() - 獲取book表內紅樓夢的所有作者 # 可解決外來鍵重名問題
from app03 import models as m3 # 第三種方式,全自動建立 # 查詢紅樓夢這本書的所有作者 book = m3.Book.objects.filter(title='紅樓夢').first() print(book) # 通過 related_name="authors" print(book.authors.all()) # 通過反向查詢 被relate_name代替無法操作 # print(book.author_set.all()) # 正向查詢 查詢作者名叫n1的所有書籍 a = m3.Author.objects.filter(name='n1').first() print(a) print(a.books.all()) # 給紅樓夢這本書新增n這個作者 author = m3.Author.objects.filter(name='n1').first() print(author) book = m3.Book.objects.filter(title='紅樓夢').first() # 使用add新增 author.books.add(book)
方式三、半自動建立第三張表 -- 手動建立第三張表+ManyToMany建立關係(推薦使用)
注意:
through('A2B表名') :指定手動建立的中間關係表(A2B)
through_fields('A2B表內當前表關係欄位','A2B表內關係表的欄位'):中介模型
三張表都建立了內部聯絡,可以使用雙下劃綫和基於物件的正方形查詢方式
from django.db import models # Create your models here. # 手動建立第三張表,查詢還方便的查詢 class Book(models.Model): # 預設會建立id name = models.CharField(max_length=32) # 中介模型,手動指定第三張中間表是Book2Author authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book', 'author')) class Author(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name class Book2Author(models.Model): id = models.AutoField(primary_key=True) book = models.ForeignKey(to='Book', to_field='id') author = models.ForeignKey(to='Author', to_field='id')
from app02 import models as mo2 # 第二種方式 半自動 # 基於物件的查詢(存在正向反向) # 查詢紅樓夢這本書所有的作者 -正向 book = mo2.Book.objects.filter(name='西遊記').first() print(book.authors.all()) # n1作者查書名 - 反向 a = mo2.Author.objects.filter(name='n1').first() print(a.book_set.all()) # 基於雙下劃線的查詢(可以簡單忽視正反) # 查詢紅樓夢這本書所有的作者的名字 ret=mo2.Author.objects.filter(book__name='西遊記').values('name') print(ret) # 刪除,給西遊記這本書,刪除n2這個作者 ret=mo2.Book2Author.objects.filter(book__name='西遊記',author__name='n2').delete() print(ret)