聚合查询
#聚合函数
from django.db.models import Max,Min,Sum,Count,Avg
关键字:aggregate
"""
from django.db.models import Max,Min,Count,Sum,Avg
# 统计所有书平均价格
res = models.Book.objects.all().aggregate(Avg('price'))
res1 = models.Book.objects.all().aggregate(Max('price'))
res2 = models.Book.objects.all().aggregate(Min('price'))
res3 = models.Book.objects.all().aggregate(Sum('price'))
res4 = models.Book.objects.all().aggregate(Count('title'))
res5 = models.Book.objects.all().aggregate(Avg('price'),Max('price'),Min('price'),Sum('price'),Count('title')) #可以一次查询多个
print(res5)
分组查询
关键字:annotate
Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg"),
这里需要注意的是annotate分组依据就是他前面的值,
如果前面没有特点的字段,则默认按照ID分组,
这里有dept字段,所以按照dept字段分组。
value里面的参数对应的是sql语句中的select要查找显示的字段,
filter里面的参数相当于where或者having里面的筛选条件
annotate本身表示group by的作用,前面找寻分组依据,
内部放置显示可能用到的聚合运算式,后面跟filter来增加限制条件,最后的value来表示分组后想要查找的字段值。
# 1.统计每一本书的作者个数
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num')
print(res)
# 2.统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(price_min=Min('book__price')).values('price_min')
print(res)
# 3.统计不止一个作者的图书
"""
1.统计每本书对应的作者个数
2.基于上面的结果 筛选出作者个数大于1 的
"""
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('author_num')
print(res)
# 4.查询各个作者出的书的总价格
res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('sum_price')
print(res)
F与Q查询
我们之前在查询数据库的时候条件都是我们自己手写的
但是现在出现了条件是从数据库里面获取的
# F
from django.db.models import F,Q
# 1.查询出卖出数大于库存数的书籍
res = models.Book.objects.filter(maichu__gt=F('kucun'))
print(res)
# 2.将所有的书的价格 全部提高100块
models.Book.objects.update(price=F('price') + 100)
# 3.了解 尝试着将所有的书的名字后面都加上 爆款
#Q
# 1.查询书籍名称是python入门或者价格是544.44的书
res = models.Book.objects.filter(title='python入门',price=544.44)
res = models.Book.objects.filter(Q(title='python入门'),Q(price=544.44)) # 逗号就是and
res = models.Book.objects.filter(Q(title='python入门')|Q(kucun=666)) # 用来Q之后 就能够支持|表示或
res = models.Book.objects.filter(~Q(title='python入门')|Q(kucun=666)) # 波浪号 表示非
print(res)
# Q查询进阶用法 用Q产生对象 然后再使用
q = Q()
q.connector = 'or'
q.children.append(('title__icontains','p'))
# q.children.append(('kucun',666))
res = models.Book.objects.filter(q)
print(res)
括号里左边跟orm查询语句里的字段名条件书写一模一样
查询优化
# only
res = models.Book.objects.all()
res = models.Book.objects.values('title')
res = models.Book.objects.only('title')
for r in res:
# print(r.title)
print(r.price)
"""
only会将括号内的字段对应的值 直接封装到返回给你的对象中 点该字段 不需要再走数据库
一旦你点了不是括号内的字段 就会频繁的去走数据库查询
"""
# defer
res = models.Book.objects.defer('title') # defer和only互为反关系
for r in res:
print(r.title)
"""
defer会将括号内的字段排除之外将其他字段对应的值 直接封装到返回给你的对象中 点该其他字段 不需要再走数据库
一旦你点了括号内的字段 就会频繁的去走数据库查询
"""
# select_related
res = models.Book.objects.select_related('publish')
res1 = models.Author.objects.select_related('author_detail')
# res = models.Book.objects.all()
for r in res1:
print(r.author_detail)
print(r.author_detail.phone)
print(r.author_detail.addr)
"""
select_related 会自动帮你做连表操作 然后将连表之后的数据全部查询出来封装给对象
select_related括号内只能放外键字段
并且多对多字段不能放
如果括号内外键字段所关联的表中还有外键字段 还可以继续连表
select_related(外键字段__外键字段__外键字段...)
"""
# prefetch_related
res = models.Book.objects.prefetch_related('publish')
# print(res)
for r in res:
print(r.publish.name)
"""
prefetch_related 看似连表操作 其实是类似于子查询
prefetch_related括号内只能放外键字段
并且多对多字段不能放
如果括号内外键字段所关联的表中还有外键字段 还可以继续连表
select_related(外键字段__外键字段__外键字段...)
"""
"""
第一个 内部自动连表 消耗的资源就在连表上 但是走数据库的次数较少
第二个 内部不做连表 消耗的资源就在查询次数上 但是给用户的感觉跟连表操作一样
"""
orm查询常见字段
orm中常见字段
AutoField(primary_key=True)
CharField(max_length=32) varchar(32)
IntegerField() int
BigIntegerField() long
DateField()
auto_now:每次修改数据的时候 都会更新该字段
auto_now_add:只在创建数据的时候 才会自动将创建时间添加 后续不会再自动修改了
DecimalField()
BooleanField(Field)
- 布尔值类型
该字段在存储数据的时候 你只需要传布尔值即可
对应到数据库中 会变成0/1
TextField(Field)
- 文本类型
存大段文本
EmailField(CharField) varchar(...)
FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
# 自定义char类型字段
class MyCharField(models.Field):
def __init__(self,max_length,*args,**kwargs):
self.max_length = max_length
super().__init__(max_length=max_length,*args,**kwargs)
def db_type(self, connection):
return 'char(%s)'%self.max_length
如果你使用的是django2.X版本 你在建数据库表关系的时候
你需要手动指定两个参数
(你要手动告诉django 级联更新 级联删除 是否建外键约束)
on_delete
db_constraint
django orm中的事务操作
ACID:
原子性
一致性
隔离性
持久性
commit
rollback
要么同时成功要么同时失败
from django.db import transaction
with transaction.atomic():
# 在该代码块中所写的orm语句 同属于一个事务
# 缩进出来之后自动结束