9、模型层(聚合、分组、F/Q查询)
聚合查询
关键字: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'))
分组查询
关键字:annotate
分组查询就是mysql里的 group by,按照什么来分组,就相当于是把多条记录压缩成一条。
正向反向查询的规则在这里一样受用。
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。
不出意料的是,我们也要倒入模块。
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)
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)) # esc下面那个键 波浪号 表示非
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)
Django开启事务
from django.db import transaction
with transaction.atomic():
# 在这里写的orm语句属于同一个事务,不用写什么提交,回滚之类的。
# 缩进出来之后自动结束事务
models.AutoField(primary_key=True)
models.CharField(max_length=32) # varchar(32)
models.IntergeField() # int()
models.DateField() # date
models.DateTimeField() # datetime
auto_now
auto_now_add
models.DecimalField() # float()
models.BooleanField()
给这个字段传布尔值会自动转换成数字0或1
一般用在状态二选一
TextField()
存储大段文本(bbs项目会使用)
EmailField()
存储邮箱格式数据
FileField()
存储数据路径(bbs项目会使用)
"""自定义字段"""
from django.db.models import Field
class MyCharField(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
常见参数
max_length
varbose_name
default
null
auto_now
auto_now_add
to
unique
db_index
choices
# choices参数
创建用户表
性别
两到三种状态
学历
也是有限个
在职状态
也是有限个
婚姻
也是有限个
...
"""针对某个字段可以列举完全的情况 一般都是使用choices参数"""
class Server(models.Model):
host = models.CharField(max_length=32)
status_choices = (
(1,'在线'),
(2,'待上线'),
(3,'宕机'),
(4,'待上架')
)
status = models.IntegerField(choices=status_choices)
desc_choices = (
('哈哈','哈哈哈哈哈哈'),
('呵呵','呵呵呵呵呵呵'),
('嘿嘿','嘿嘿嘿嘿嘿嘿'),
('嘻嘻','嘻嘻嘻嘻嘻嘻'),
)
desc = models.CharField(max_length=32,choices=desc_choices)
# 获取对应关系
.get_字段名_display()

浙公网安备 33010602011771号