表结构设计
多对多关系表创建外键,典型例子:书--作者--出版社,书与作者的关系就可以看作是多对多关系。
# 表结构设计 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对象)