day 61 聚合查询,分组查询,F与Q查询,orm中常见的字段,查询优化,django中的orm事务操作

   聚合查询

   #聚合函数
   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语句 同属于一个事务
# 缩进出来之后自动结束

 


猜你喜欢

转载自www.cnblogs.com/wwei4332/p/11739133.html