Django模型层2 一、聚合查询 二、分组查询 三、F与Q查询 四、orm字段及参数 五、自定义char字段 六、orm中的事务操作

聚合函数

即 Max,Min,Sum,Avg,Count 几种函数。

聚合函数必须用在分组之后,没有分组默认整体就是一组。

注意事项:

  1. 使用聚合函数需要先使用关键字:aggregate

  2. 还需要将聚合函数模块导入

    (只要跟数据库相关的功能都在django.db.models里面;

    如果不在,可能在django.db里面)

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

# 1.筛选出价格最高的书籍的
res = models.Book.objects.aggregate(mr = Max('price'))
print(res)
# {'mr': Decimal('666.60')}

# 2.求书籍总价格
res = models.Book.objects.aggregate(sm = Sum('price'))
print(res)
# {'sm': Decimal('1286.30')}

# 3.求书籍平均价格
res = models.Book.objects.aggregate(av = Avg('price'))
print(res)
# {'av': 128.63}

# 4.一起使用
res = models.Book.objects.aggregate(Max('price'),Min('title'),Count('price'),Avg('price'))
print(res)
# {'price__max': Decimal('666.60'), 'title__min': '大主宰', 'price__count': 10, 'price__avg': 128.63}

二、分组查询

什么时候需要分组?

1. 统计每一个部门的平均薪资
2. 统计每一个部门的男女比例

利用group by进行分组查询

注意事项:

  1. 分组需要使用关键字:annotate

  2. 也需要借助于聚合函数

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

# models.哪个表名 ,就对哪个表分组


# 1.统计每一本书的作者个数 书名 和对应的作者人数
res = models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')
print(res)

# 2.统计出每个出版社卖的最便宜的书的价格  出版社的名字 价格
res = models.Publisher.objects.annotate(min_price=Min('book__price')).values('name','min_price')
print(res)

# 按照其他字段分组
res = models.Publisher.objects.values('addr').annotate(min_date=Min('book__publish_date')).values('name','min_date')
print(res)

# 3.统计不止一个作者的图书
# (1.先拿书及对应的作者数
# (2.再筛选出大于一的图书  书名 作者数目
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
print(res)


# 4.查询各个作者出的书的总价格  作者名字  总价格
res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
print(res)

三、F与Q查询

用之前需要先将F和Q类导入。

1. F类

F能够通过字符串获取到表中对应的字段的值。

# from django.db.models import F,Q

# 1. 查询库存数大于卖出数的书籍
# 后面的条件是来自于数据库的其他字段值
res = models.Book.objects.filter(kun_cun__gt = F('inventory')).values('title')
print(res)

# 2. 将所有书的价格上涨100块
models.Book.objects.all().update(price=F('price') + 100)


# 3.将所有书的名称后面全部加上 "爆款" 后缀
# (了解知识点) 操作字符串数据需要借助于Concat方法
from django.db.models.functions import Concat
from django.db.models import Value
ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))

2. Q类

Q类可以传一个条件参数实例化一个对象,通过这个Q对象可以和别的Q对象在筛选条件时进行‘or’或者‘not’的判断。

# from django.db.models import F,Q

# Q包裹之后,用逗号还是and关系,默认就是为and2
res = models.Book.objects.filter(Q(title='三国演义'),Q(kun_cun=500))  

#  |就是or的关系
res = models.Book.objects.filter(Q(title='最终进化')| Q(price=500)) 
#  ~就是not关系
res = models.Book.objects.filter(~Q(title='星辰变')| Q(price=500))
print(res)


# Q对象高级用法
q = Q()
q.connector = 'or'  # 默认是and,改成or,内部就是在修改Q类的default值
q.children.append(('title','武动乾坤'))
q.children.append(('price__gt',500))
# 将两个条件添加进q对象中,直接比较q对象
res = models.Book.objects.filter(q)
res = models.Book.objects.filter(~q)  # 取反
print(res)

四、orm字段及参数

  1. CharField varchar

  2. IntegerField int

  3. BigIntegerField bigint

  4. EmailField varchar(254)

  5. DateField

  6. DateTimeField

    • auto_now:每次修改数据的时候 都会自动将当前修改时间更新上去 实时更新

    • auto_now_add:在创建数据的时候 会将当前时间自动记录 之后不会自动修改 除非你人为修改

  7. AutoField auto_increment

  8. BooleanField 布尔值

    • 用该字段存储时,只需要传布尔值True或False,它会自动存成1/0
  9. TextField 专门用来存大段文本

  10. FileField 专门用来文件路径 '/etc/data/a.txt'

    • upload_to = '/etc/data'

    • 给该字段传值的时候,可以直接传文件对象

    • 会自动将文件对象保存到upload_to后面指定的文件路径中

    • 然后将路径保存到数据库

  11. 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

六、orm中的事务操作

1. 什么是事务

事务就是一组原子性的SQL语句,或者说一个独立的工作单元。

如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询。

如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。

也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。

不成功便成仁。

2. 四大特性

ACID

  1. 原子性(atomicity)

    事务操作必须被视为一个不可分割的最小工作单元。

    整个事务中的所有操作要么全部提交成功,要么全部失败回滚。

    对于一个事务来说,不可能只执行其中的一部分操作。

    这就是事物的原子性。

  2. 一致性(consistency)

    数据库总是从一个一致性的状态转换到另外一个一致性的状态。

    确保数据库在事务进行前后的数据总量保持一致。

  3. 隔离性(isolation)

    简单地说,就是事务与事务之间是隔离的。

    这也就意味着,一个事务所做的修改在最终提交以前,对其他事务是不可见的。

    也就是说,当某一条数据开始进行一个事务但没有提交的时候,另一个事务也要对这条数据进行修改,那后面一个事务看见的就是数据没有被第一个事物修改过的最初的样子。

  4. 持久性(durability)

    一旦事务提交,则其所作的修改就会永久保存到数据库中。

    即使此时系统崩溃,修改的数据也不会丢失。

3. 三大范式

  1. 第一范式

    每一列属性都是不可再分的属性值,确保每一列的原子性。

  2. 第二范式

    每一行的数据只能与其中一列相关,确保表中的每列都和主键相关,避免数据重复。

  3. 第三范式

    数据不能存在传递关系,即每列都跟主键列直接相关,而不是间接相关。