一、多表之间的关系
1 一对一: 2 1️⃣ 必须对先被关联表添加记录(即没有外键的表) 3 2️⃣ 关联表中的关联字段可以直接使用被关联表时的对象 4 创建关联表时,可直接使用外键 id 传入被关联表中未被绑定的元素 5 6 一对多: 7 1️⃣ 必须对先被关联表添加记录(即没有外键的表) 8 2️⃣ 关联表中的关联字段可以直接使用被关联表时的对象 9 3️⃣ 过滤出被关联表的对象记得加上 first() 处理 10 4️⃣ 让关联表 id = 被关联表 id 11 12 多对多: 13 1️⃣ 添加关联关系使用 book.authors.add(1,2),表示的是往中间表插入记录,没有返回值 14 book:表示的是对应的 book 某本书,而不是在创建表时的 authors 属性 15 1,2:表示的是 authors.id 16 2️⃣ book.authors.add(*(1,2)) 17 3️⃣ add(参数1,参数2) # 参数可以直接传对象,以逗号分隔
1 解除绑定关系
remove() # 需要传参数,参数即需要解除的 id 或者对象,可以是多个,用逗号分隔;也可用解压的方式(*(参数1,参数2))
2 一次性清空绑定关系
clear() # 不用传参数
3 先清空再设置
set() # 底层原理是先清空,然后再使用 add() 函数来添加;参数必须是可迭代对象
二、多表查询的总结
authordetail = AuthorDetail.objects.filter(pk=zhf.authordetail_id) print(zhf.authordetail) # 这种情况下会查询两次,第一次是 authordetail 这个表中查询一次;第二次是 zhf.authordetail 执行查询一次
1 正向查询与反向查询
正向查询:关联字段在 A 表中,查询表 B,按字段来查询,即 A.B.字段名
反向查询:关联字段在 A 表中,由表 B 查询 表 A,按照 表名小写_set 方式来查询
如:B.a_set.all()
B.a_set 是 Manage 对象
B.a_set.all() 是 QuerySet 对象
2 正向查询方式与反向查询方式
总结 | 正向查询 | 反向查询 |
one to one | 按照字段 | 表名小写 |
one to many | 按照字段 | 表名小写_set |
many to many | 按照字段 | 表名小写_set |
三、基于双下划线的多表查询(链表查询)
Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的model 为止。
正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表
1 在使用 __ 双下划线告诉 ORM 该 JOIN 哪张表前提下的总结
总结 | 正向查询 | 反向查询 |
one to one | 按照字段 | 表名小写 |
one to many | 按照字段 | 表名小写 |
many to many | 按照字段 | 表名小写 |
四、聚合函数
form django.db.models.import Avg,Count,Max,Min,Sum # 使用 aggregate() 函数表示聚合函数 Book.objects.all.aggregate(Avg('price')) # 返回值是一个字典,可传多个参数 # 给字段重命名 Book.objects.all.aggregate(avg_price=Avg('price'))
五、分组
annotate() 为调用的 QuerySet 中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。
from django.db.models import Avg, Max, Sum, Min, Max, Count book_list = models.Book.objects.all().annotate(author_num=Count("authors")) for book in book_list: print(book.name) print(book.author_num) book_list = models.Book.objects.all().annotate(author_num=Count("authors")).values('name','author_num') print(book_list)
总结 :跨表分组查询本质就是将关联表 JOIN 成一张表,再按单表的思路进行分组查询。
1️⃣ value 在 annotate 前,表示group by 字段;在 annotate 后,表示要 select 的字段(若不写 value,默认是以基表的主键为基准)
2️⃣ filter 在 annotate 前,指的是 where 的东西;在 annotate 后面指的是 having 的东西
六、F 查询和 Q 查询
1 F 查询
Django 提供 F() 函数。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。修改操作也可以使用F函数。
from django.db.models import F,Q #评论数大于阅读数的所有书,返回的是 QuerySet 对象 Book.objects.all().filter(commit_num__gt=F('read_num')) # 对所有的书价格 +1 Book.objects.all().update(price=F('price')+1)
2 Q 查询
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 若需要执行更复杂的查询(例如 OR 语句),可以使用 Q 对象。
Q 对象可以使用 & 和 | 操作符组合起来。当一个操作符在两个 Q 对象上使用时,它产生一个新的 Q 对象。
bookList=Book.objects.filter(Q(authors__name="888")|Q(authors__name="666"))
# 等同于 SQL 语句
WHERE name ="yuan" OR name ="egon"
如果出现Q 对象,它必须位于所有关键字参数的前面 bookList=Book.objects.filter(Q(publish_Date__year=9999) | Q(publish_Date__year=8888), name__icontains="Django")