Python - Django - ORM 多对多表结构的三种方式
多对多的三种方式:
- ORM 自动创建第三张表
- 自己创建第三张表, 利用外键分别关联作者和书,关联查询比较麻烦,因为没办法使用 ORM 提供的便利方法
- 自己创建第三张表,使用 ORM 的 ManyToManyFiled(),使用此种方式创建多对多表的时候,没有 add() remove() 等方法
适用方法:
- 如果第三张表没有额外的字段,就用第一种
- 如果第三张表有额外的字段,就用第三种或第一种
方法二:
models.py:
from django.db import models # 书
class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2) def __str__(self):
return self.title # 作者
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField() def __str__(self):
return self.name # 手动创建作者和书籍关联的第三张表
# 此时在 ORM 层面,作者和书籍就没有多对多的关系了
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
author = models.ForeignKey(to="Author") # 作者 id
book = models.ForeignKey(to="Book") # 书籍 id
在数据库中添加数据
author 表:

book 表:

author2book 表:

多对多的操作:
orm.py:
import os if __name__ == '__main__':
# 加载 Django 项目的配置信息
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite2.settings")
# 导入 Django,并启动 Django 项目
import django
django.setup() from app02 import models
# 多对多的查询
# 查询 id 是 2 的作者关联的书籍的 id
ret = models.Author2Book.objects.filter(author_id=2).values_list("book_id")
print(ret) ret = [i[0] for i in ret] # 得到关联的书籍的 id
# 通过书籍的 id 查询 id 是 2 的作者关联的书籍名
ret = models.Book.objects.filter(id__in=ret)
print(ret)
运行结果:

这里的 [i[0] for i in ret] 是为了取元组中的 id:2、3,然后通过 id:2、3 获取它们的书籍
方法三:
models.py:
from django.db import models # Create your models here. # 书
class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2) def __str__(self):
return self.title # 作者
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
# 通过 through,through_fields 来指定使用创建的第三张表来构建多对多的关系
books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book",)) def __str__(self):
return self.name # 手动创建作者和书籍关联的第三张表
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
author = models.ForeignKey(to="Author") # 作者id
book = models.ForeignKey(to="Book") # 书籍 id class Meta:
unique_together = ("author", "book") # 建立唯一约束
在数据库中添加与 app02 一样的数据
多对多的操作
orm.py:
import os if __name__ == '__main__':
# 加载 Django 项目的配置信息
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite2.settings")
# 导入 Django,并启动 Django 项目
import django
django.setup() from app03 import models ret = models.Author.objects.get(id=2).books.all() # 获取 id 为 2 的作者关联的所有书籍
print(ret)
运行结果:

该方法中没有 remove() 方法,可以使用下面的方法:
models.Author2Book.objects.get(author_id=1, book_id=1).delete()
没有 django ORM 封装的那些快捷方法,我们要自己手动修改第三张表
Python - Django - ORM 多对多表结构的三种方式的更多相关文章
- Django创建多对多表关系的三种方式
方式一:全自动(不推荐) 优点:django orm会自动创建第三张表 缺点:只会创建两个表的关系字段,不会再额外添加字段,可扩展性差 class Book(models.Model): # ... ...
- 多表连接的三种方式 HASH MERGE NESTED
多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP------------------------------------------------------20 ...
- 多表连接的三种方式详解 hash join、merge join、 nested loop
在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式.多表之间的连接有三种方式:Nested Loops,Hash Join 和 Sort Merge Join.具体适用哪 ...
- python 获取表单的三种方式
条件:urls.py文件中配置好url的访问路径.models.py文件中有Business表. 在views.py文件中实现的三种方式: from app01 improt models def b ...
- 示例讲解PostgreSQL表分区的三种方式
我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 表分区是解决一些因单表过大引用的性能问题的方式,比如某张表过大就会造成查询变慢,可能分区是一种解决方案.一般建议 ...
- [python]django的mode设置表结构和serializers序列化数据
框架使用的库版本 python3.6.5 Django-2.0.6 djangorestframework-3.8.2 mysqlclient-1.3.12 1.项目结构声明,数据库在setting. ...
- 多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP
在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点 ...
- form表单提交三种方式,demo实例详解
第一种:使用type=submit 可以直接提交 <html> <head> <title>submit直接提交</title> </head& ...
- Python - Django - ORM 多对多操作
models.py: from django.db import models # 出版社 class Publisher(models.Model): id = models.AutoField(p ...
随机推荐
- 常见的C语言编程规范
头文件: 1.头文件中适合放置接口的声明,不适合放置实现. 2.头文件应向稳定的方向包含,产品依赖于平台,平台依赖于标准库. 3. .c/.h文件禁止包含用不到的头文件. 4.每一个.c文件应有一个同 ...
- navcat导入mysql.sql出现:2006, 'MySQL server has gone away'
navcat导入mysql.sql出现:2006, 'MySQL server has gone away' OperationalError (2006, ‘MySQL server has gon ...
- (转载) 从0开始搭建SQL Server AlwaysOn 第二篇(配置故障转移集群)
这一篇是从0开始搭建SQL Server AlwaysOn 的第二篇,主要讲述如何搭建故障转移集群,因为AlwaysOn是基于Windows的故障转移集群的 在讲解步骤之前需要了解一下故障转移集群仲裁 ...
- 洛谷 P2296 寻找道路 题解
每日一题 day42 打卡 Analysis 首先,预处理,把每条边反向. 从终点开始bfs,标记从终点开始可以走到的点. 第二步,枚举每一个点,如果这个点没有被标记,则枚举它的每一条出边(反向后的) ...
- BZOJ 5093: [Lydsy1711月赛]图的价值 第二类斯特林数+NTT
定义有向图的价值为图中每一个点的度数的 \(k\) 次方之和. 求:对于 \(n\) 个点的无向图所有可能情况的图的价值之和. 遇到这种题,八成是每个点单独算贡献,然后累加起来. 我们可以枚举一个点的 ...
- 微信小程序微信登录
开发接口 登录 wx.login wx.checkSession 签名加密 小程序登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系. 登录流程时序 ...
- 《挑战30天C++入门极限》新手入门:C/C++中数组和指针类型的关系
新手入门:C/C++中数组和指针类型的关系 对于数组和多维数组的内容这里就不再讨论了,前面的教程有过说明,这里主要讲述的数组和指针类型的关系,通过对他们之间关系的了解可以更加深入的掌握数组和指 ...
- Deepin Create/Delete Folder refresh
Did u have a problem whth the deepin file manager,Everthime I create/delete a Folder of File i have ...
- CStatic 控件设置文本,不能重回问题
CStatic m_page_text_; m_page_text_.SetWindowText(str); CRect rt; m_page_text_.GetWindowRect(&rt) ...
- Java 中List集合中自定义排序
/* 集合框架的工具类. Collections:集合框架的工具类.里面定义的都是静态方法. Collections和Collection有什么区别? Collection是集合框架中的一个顶层接口, ...