![]()
1、关联管理器
# add(obj1[, obj2, ...])
book_obj.authors.add(*[1,3])
# 将id=1和id=3的作者对象添加到这本书的作者集合中
# 应用: 添加或者编辑时,提交作者信息时可以用到.
# remove(obj1[, obj2, ...])
author_obj = Author.objects.get(id=1)
book_obj = Book.objects.get(id=2)
author_obj .book_set.remove(book_obj)
# 对于ForeignKey对象,这个方法仅在null=True时存在。
# clear()
author_obj = Author.objects.get(id=1)
author_obj.book_set.clear()
# 注意这样不会删除对象 —— 只会删除他们之间的关联。
# set()
# 先清空,在设置,编辑书籍时即可用到。(其实不会,因为创建表时已设置好自动去除)
book = models.Book.objects.filter(title="独孤九剑").first()
book.authors.set([1, 3])
详细请参考
2、聚合查询
# 计算所有图书的平均价格
# from django.db.models import Avg, Max, Min
books = models.Book.objects.aggregate(Avg("price"),Max("price")...)
# aggregate() 是QuerySet 的一个终止句,返回一个包含一些键值对的字典。
# Avg可改为avg_price是指定一个名称,如果不指定则是字段+聚合包含的名称
3、分组查询(一条公式看懂)
# 简易版
# 无关联表情况下
# 查询每一个部门名称以及对应的员工数:
# SQL
SELECT dep,COUNT(id) from app01_emp GROUP BY dep;
# dep,COUNT(id)(以dep及id总数来显示),从app01_emp的表里获取,以部门分组
# pycharm
from django.db.models import Count, Avg, Sum
query_result = models.Emp.objects.values('dep').annotate(Count('id'))
# values('')(以指定元素分组),annotate分组查询必要语句,Count('')(统计指定元素)
# 表有关联情况下
# 查询每一个部门名称以及对应的员工数
# SQL里
SELECT app01_dep.title,COUNT(app01_emps.id) FROM app01_emps LEFT JOIN app01_dep on app01_emps.dep_id=app01_dep.id GROUP BY app01_emps.dep_id;
# app01_dep.title,COUNT(app01_emps.id)(因为是跨表形式,要在显示内容前加上(title)前加上前缀(即应用.表名),COUNT同理)
# left join...on(表1和表2的关联为on...) group of(以什么分组,由于是多表,所以也要加前缀)
# pycharm里
query_result = models.Emps.objects.values('dep__title').annotate(Count('id'))
# pycharm里已自动关联,所以仅需填入需要的值无需再做关联,跨表值也仅需表名作为前缀即可
# 复杂版
# 练习:查询各个作者出的书的总价格
# SQL里
SELECT app01_author.`name`,SUM(app01_book.price) FROM app01_author
LEFT JOIN app01_book_authors
on app01_author.id=app01_book_authors.author_id
LEFT JOIN app01_book
ON app01_book.id=app01_book_authors.book_id
GROUP BY app01_author.`name`;
# app01_author.`name`,SUM(app01_book.price)(查询且要显示的元素)
# 多个left join是因为book表和author没有直接关联,需要借助关系表book——author,group by 以什么分组
# pycharm里
query_result = models.Author.objects.annotate(num=Sum('book__price')).values('name', 'num')
4、F(动态获取字段值)Q(关键字)查询
# Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
# Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
models.Emp.objects.filter(salary__lt=F("age") * 2)
# Q 对象可以使用 & 、 | 和 ~(与 或 非)操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。
models.Book.objects.filter(Q(price__gt=300)|~Q(Q(pub_date__year=2019)&Q(pub_date__month=3)))
5、图书馆管理系统