Day 54 ORM聚合查询/分组查询/F查询和Q查询/事务

聚合查询

讲聚合查询之前首先讲讲ORM中的聚合函数

在django的ORM中,我们需要先从模块中导入聚合函数

from django.models import Max, Min, Sum, Count, Avg

然后利用aggregate方法才进行聚合查询

示例

from django.models import Max, Min, Sum, Count, Avg

# 1.筛选出价格最高的书籍
res = models.Book.objects.aggregate(mr=Max('price'))
print(res)
# 2.求出书籍的总价格
res = models.Book.objects.aggregate(sm=Sum('price'))
print(res)
# 3.求书籍平均价格
res = models.Book.objects.aggregate(Avg=Avg('price'))
print(res)
# 4.可以一起使用
res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('price'),Avg('price'))

分组查询

ORM分组查询借助于annotate方法和聚合函数,相当于SQL语句中的group by

from django.models import Max, Min, Sum, Count, Avg

# 1.统计每一本书的作者个数 书名 和对应的作者人数
res = models.Book.objects.annotate(author_num=Count('author__id')).values('name', author_num)
print(res)
# 2.统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(min_price=Min(book__price)).values('name', 'min_price')
print(res)
# 3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count(author__id)).filter(author_num__gt=1).values('title')
# 4.查询各个作者出的书的总价格
res = models.Author.objects.annotate(sum_price=Sum(book__price)).values('name', 'sum_price')

F与Q查询

F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较,如果我们要对两个字段的值做比较,那该怎么做呢

Django提供F()来做这样的比较.F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值

实例1:

查询出卖出数大于库存数的商品

from django.db.models import F
res = models.Product.objects.filter(sales__gt=F('stocks'))
print(res)

F可以帮我们取到表中某个字段对应的值来当作我的筛选条件,而不是我认为自定义常量的条件了,实现了动态的比较的效果

Django支持F()对象之间以及F()对象和常熟之间的加减乘除和取模的操作.基于此可以对表中的数值类型进行数学运算

将每个商品的价格提高50块

models.Product.objects.update(price=F('price')+50)

注意

如果要修改的是char字段

可以使用对字符串进行拼接的Concat操作,并且要加上拼接值Value

把所有数名后面加上'新款'

from django.db.models.functions import Concat
from django.db.models import Value
res = models.Product.objects.update(name=Concat(F('name'), Value('新款')))

Concat中参数位置决定了拼接是在头部拼接还是尾部拼接,Value里面要新增的拼接值

Q查询

filter()等方法中逗号隔开的条件是与关系,如果你需要执行更复杂的查询(例如or语句),你可以使用Q对象

示例1:

查询卖出数大于100或者价格小于100块的

from django.db.models import Q
models.Product.objects.filter(Q(sales__gt=100)|Q(price__lt=100))

对条件包裹一层Q的时候,filter即可支持交叉并的比较符

示例2:

查询 库存数是100并且卖出数不是0的产品

models.Product.objects.filter(Q(stocks=100)&~Q(sales=0))

可以用~操作符取反,这允许组合正常的查询和取反(NOT)查询

示例3:

查询产品名包含新款,并且库存数大于60的

models.Product.objects.filter(Q(stocks__gt=60),name__contains='新款')

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面

ORM字段及参数

常用字段 作用
CharField 字符类型,必须提供max_length参数,表示字符长度
AutoField int自增列,必须填入参数primary_key=True
IntegerField 一个整数类型,范围在-2147483648 to 2147483647
DateField 日期字段,日期格式 YYYY=MM-DD
DateTimeField 日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
TextField 文本类型
EmailField 字符串类型,Django Admin以及ModelForm中提供验证机制
FileField 字符串,路径保存在数据库,文件上传到指定目录,参数(upload_to="",storage=None)
DecimalField 10进制小数,参数(max_digits,decimal_places)数字允许的最大位数,小数最大位数

自定义char字段

class FixedCharField(models.Field):
    """
    自定义的char类型的字段类
    """
    def __init__(self, max_length, *args, **kwargs):
        self.max_length = max_length
        super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs)

    def db_type(self, connection):
        """
        限定生成数据库表的字段类型为char,长度为max_length指定的值
        """
        return 'char(%s)' % self.max_length


class Class(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=25)
    # 使用自定义的char类型的字段
    cname = FixedCharField(max_length=25)

ORM中的事务操作

https://www.cnblogs.com/2222bai/p/11779042.html/

四个特性

原子性:原子意为最小的粒子,即不能再分事务,要么全部执行,要么全部取消

一致性:指事务发生前发生后,数据的总额依然匹配

隔离性:简单点说,某个事务的操作对其他事务是不可见的

持久性:当事务完成后,其影响应该保留下来,不能撤销,只能通过'补偿性事务'来抵消

from django.db import transaction

with transaction.atomic():
    # 在缩进中书写数据库操作
    # 该缩进内的所有代码,都是一个事务

猜你喜欢

转载自www.cnblogs.com/2222bai/p/11953452.html