目录
多对多关联与中介模型
一 多对多关联的三种方式
# 多对多关联关系的建立有三种方式。
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) # 不能用了