Django-ORM之ManyToManyField的使用-多對多關系


表結構設計

多對多關系表創建外鍵,典型例子:書--作者--出版社,書與作者的關系就可以看作是多對多關系。

 # 表結構設計
 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對象)
 ​


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM