表結構設計
多對多關系表創建外鍵,典型例子:書--作者--出版社,書與作者的關系就可以看作是多對多關系。
# 表結構設計 class Book(models.Model): title = models.CharField(max_length=32) pub = models.ForeignKey('Publisher', on_delete=models.CASCADE) #與出版社之間建立多對一外鍵 class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book') # 描述多對多的關系 不生成字段 生成關系表
數據遷移
如果是在新的app中進行功能的設計,可以使用 python manage.py makemigrations app(應用名) 進行數據的遷移,數據遷移完之后會生成三張表,這是情理之中的事,因為多對多關系的兩張表要建立連接的時,需要借助第三張表來維護二者的關系,這里會自動生成第三張表,如圖:
【新建測試表結構】

1 from django.db import models 2 3 # Create your models here. 4 class Publisher(models.Model): 5 name = models.CharField(max_length=32) 6 city = models.CharField(max_length=32) 7 8 def __str__(self): 9 return "<Publisher object: {} {}>".format(self.id, self.name) 10 11 class Author(models.Model): 12 name = models.CharField(max_length=32) 13 age = models.IntegerField() 14 phone = models.CharField(max_length=11) 15 16 def __str__(self): 17 return "<Author object: {} {}>".format(self.id, self.name) 18 19 class Book(models.Model): 20 title = models.CharField(max_length=32) 21 publish_date = models.DateField(auto_now_add=True) 22 price = models.DecimalField(max_digits=5, decimal_places=2) 23 memo = models.TextField(null=True) 24 # 創建外鍵,關聯publish 25 publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE) 26 # 創建多對多關聯author 27 author = models.ManyToManyField(to="Author") 28 29 def __str__(self): 30 return "<Book object: {} {} {} {}>".format(self.id, self.title,self.price,self.author)
基於對象的正向查詢
book_obj = models.Book.objects.get(pk=1) print(book_obj) print(book_obj.title) print(book_obj.author) # 關系管理對象,通過books可以得到兩張表的關系,輸出:app01.Book.None print(book_obj.author.all()) # 所關聯的所有對象,輸出:<QuerySet [<Author: <Author object: 1 金老板>>, <Author: <Author object: 2 小哪吒>>]>
基於對象的反向查詢
author_obj = models.Author.objects.get(pk=1) print(author_obj) print(author_obj.book_set) print(author_obj.book_set.all()) print(author_obj.name)
基於字段的正向查詢
# 查找作者嘰喳寫的書 book_obj = models.Book.objects.filter(author__name='嘰喳') print(book_obj) print(book_obj.first().title)
基於字段的反向查詢
# 查找《嘰嘰喳喳》的作者 author_obj = models.Author.objects.filter(book__title='嘰嘰喳喳') print(author_obj)
關系管理對象的方法set、add、remove、clear
all 關聯的所有的對象
author_obj = models.Author.objects.get(pk=1) book_obj = models.Book.objects.get(pk=1) print(author_obj.book_set.all()) print(book_obj.author.all())
set 設置多對多關系,兩種方式,添加對象列表
author_obj.book_set.set([3,4]) # 這個作者寫的哪些書 author_obj.book_set.set(models.Book.objects.filter(pk__in=[3,4]))
add 添加多對多關系,兩種方式,直接添加關系對象就好
author_obj.book_set.add(3,4) author_obj.book_set.add(*models.Book.objects.filter(pk__in=[3,4]))
remove 刪除多對多關系,兩種方式,直接移除關系對象
author_obj.book_set.remove(3,4) author_obj.book_set.remove(*models.Book.objects.filter(pk__in=[3,4]))
clear 清空當前對象多對多關系
author_obj.book_set.clear()
關系管理對象的方法create
author_obj.book_set.create(title='嘰嘰喳喳的世界',publisher_id=2,price=99.9) book_obj.author.creat(name='小提莫',age=23,phone='13822567070')
【配合HTML模板】
# 獲取對應的一個或者多個book的id,注意當或去多個值時使用的時getlist books = request.POST.getlist('books') # 新建作者 author_obj = models.Author.objects.create(name=name) #第一個name是Author表的字段名 # 給作者和書籍綁定關系 author_obj.books.set(books) # 【id,id】自動把兩者的信息進行匹配保存
刪除對象
# 直接調用delete方法刪除即可 pk = request.GET.get("pk") # 過的主鍵 obj = models.Auther.objects.filter(id=pk) # 通過主鍵獲得整個對象 obj.delete() # 刪除對象 這里刪除對象之后,會直接把與之相關的外鍵關系刪除,而不會刪除關系對應的圖書對象
自定義外鍵
自己手動創建
手動創建關系表,所有的信息維護也需要手動進行增刪改查
class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book_Author(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField()
自己創建 + ManyToManyField
手動創建關系表,再借用through函數綁定到關系表,關系信息的維護仍是手動
class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField(Book, through='Book_Author') class Book_Author(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField() # 添加關系 #方式一: m1 = BookAuthor(author=author對象,book=book對象) #方式二: m2 = BookAuthor.objects,create(author=author對象,book=book對象)