Django框架:8、聚合查询、分组查询、F与Q查询、ORM查询优化、ORM事务操作、ORM常用字段类型、ORM常用字段参数
Django 数据库
一、聚合查询
聚合函数:
- Max
- 求最大值
- Min
- 求最小值
- Sun
- 求和
- Cont
- 统计数量
- Avg
- 求平均值
使用方法
- 类名.object.aggreate(聚合函数(‘字段名’))
在MySQL数据库中,聚合函数需要在分组后(group by)才能使用
在Django中,可以直接使用,需要搭配关键词:aggtegate
1、导入模块
from django.db.models import Max,Min,Sun,Count,Avg
2、res = Book.objects.aggregate(Max('price'), Count('pk'), 最小价格=Min('price'), allPrice=Sum('price'),平均价格=Avg('price'))
二、分组查询
补充
问题:
在执行orm分组查询中,如果报错,并且有关键字sql_mode strict mode
解决方法:
移除sql_mode中的only_full_group_by
使用方法
- 按表分组
- models.表名.objects.annotate()
- 按指定字段分组
- models.表名.objects.values('字段名').annotate()
按表分组
# 分组查询
# 统计每一本书的作者个数
# res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('title', 'author_num')
# print(res)
# 统计出每个出版社卖的最便宜的书的价格
# res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')
# print(res)
# 统计不止一个作者的图书
# 1.先统计每本书的作者个数
# res = models.Book.objects.annotate(author_num=Count('authors__pk'))
# 2.筛选出作者个数大于1的数据
# res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('title',
# 'author_num')
# print(res)
# 查询每个作者出的书的总价格
# res = models.Author.objects.annotate(总价=Sum('book__price'),count_book=Count('book__pk')).values('name','总价','count_book')
# print(res)
按字段分组
res = models.Book.objects.values('publish_id').annotate(count_pk=Count('pk')).values('publish_id', 'count_pk')
print(res)
三、F查询与Q查询
1、F查询
当查询条件不是明确的,也需要从数据库中获取,就需要使用F查询,它可以直接对一整个字段下的数据进行操作
使用方法
1、导入模块
from django.db.models import F
2、具体用法
# 1.查询库存数大于卖出数的书籍
# res = models.Book.objects.filter(kucun__gt=F('maichu'))
# 2.将所有书的价格涨800
# models.Book.objects.update(price=F('price') + 800)
# 3.将所有书的名称后面追加爆款
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F('title'), Value('新款')))
2、Q查询
ORM中,所有的数据条件都是使用逗号隔开,彼此的关系默认都是and的关系
Q:可以将多个查询条件的关系做修改
使用方法
1、导入模块
from django.db.models import Q
2、具体用法
# and关系
models.Book.objects.filter(Q(pk=1),Q(title='三国'))
# or关系
models.Book.objects.filter(Q(pk=1) | Q(title='三国'))
# not关系
models.Book.objects.filter(~Q(pk=1),Q(title='三国'))
3、Q查询进阶操作
说明
通过生成Q对象,并提前设置好条件,直接将Q对象传入filter中当作条件进行查询
具体用法
1、导入Q模块
from django.db.models import Q
2、产生Q对象
q_obj = Q()
3、设置链接条件(默认为and,可以修改为or)
q_obj.connector = 'or'
4、添加查询条件 (支持添加多个查询条件)
# 查询条件1
q_obj.children.append(('pk', 1))
# 查询条件2
q_obj.children.append(('price__gt', 2000))
5、传入Q对象,进行查询(# 查询支持直接填写q对象)
res = models.Book.objects.filter(q_obj)
print(res)
四、ORM查询优化
ORM查询优化是指,在我们使用的ORM语句进行查询时,它的底层帮助我们做了很多的优化,其目的都是为了节省内存空间
ORM默认都是惰性查询
- 当我们不执行打印操作的时候,ORM语句不会执行,想要看到这个现象需要打开日志功能,即在配置文件中进行配置
ORM查询自带分页
- 可以通过日志展示的代码查看,日志返回的sql代码后端会有一个limit
only与defer
- 特别说明
1、only与defer
前置说明
这里需要做一些具体的说明,方便大家理解only和defer。
当我们在Django中执行ORM操作进行数据库查询的时候,其实内部的代码把所有的数据库中的记录,都封装到了ORM操作的对象中去了,因此我们可以通过点的方式或是索引等方式查询到对应的数据。
但是当遇到查询的时候需要查询不在条件中的记录时,就需要执行sql语句进行查询了。
比如我们在查询的时候,需要的结果在外键对应的表中,这时候去外键对应的表中查询数据,就需要执行sql语句进行查询,并且查询一条记录需要执行一次sql语句
而我们的only的作用是把写在括号内的参数中的字段的值封装到对象中,让后续查找的时候 不需要执行sql语句进行查询,加快执行速度。或是起到一个减少代码封装的数据量,加快运行的作用。
而defer则是和only相反,写在括号内的字段值不会被封装到对象中,别的字段反而会被封装到对象中。
only
获取数据对象+含有指定字段对应的数据
res = models.Book.objects.only('title', 'price')
print(res) # queryset [数据对象、数据对象]
for obj in res:
print(obj.title) # 点击括号内填写的字段 不走SQL查询
print(obj.price)
print(obj.publish_time) # 可以点击括号内没有的字段获取数据 但是会走SQL查询
defer
res = models.Book.objects.defer('title', 'price')
print(res) # queryset [数据对象、数据对象]
for obj in res:
print(obj.title) # 点击括号内填写的字段 走SQL查询
print(obj.price)
print(obj.publish_time) # 点击括号内没有的字段获取数据 不走SQL查询
五、ORM事务操作
事务的四大特性(ACID)
原子性、一致性、隔离性、持久性
相关SQL关键字
1、开启事务
start transaction;
2、回滚
rollback;
3、提交
commit;
4、设置回滚节点
savepoint;
相关重要概念
脏读、幻读、不可重复读、MVCC多版本控制...
1、Django开启事务的方法
方法一:全局有效
# 配置文件的数据库相关配置中添加键值对
"ATOMIC_REQUESTS": True
方法二:装饰器
# 局部有效,这个视图函数内的一些orm操作属于一个事务
from django.db import transaction
@transaction.atomic
def index():pass
方法三:上下文管理
# 局部有效,写在with下方的orm操作属于一个事务
from django.db import transaction
def reg():
with transaction.atomic():
pass
注意事项
这里的三种方法有个小区别,前面两种方式执行事务,视图层函数遇到返回值类型不对,orm操作可以正常执行的,但是with上下文管理的方式操作事务的话,则不行,操作会回退。
六、ORM常用字段类型
1、默认字段类型
名称 | 含义 |
---|---|
AutoField() | Int自增列 必须填入参数 primary_key=True 当model中如果没有自增列 则自动会创建一个列名为id的列 |
CharField() | 字符类型 必须提供max_length参数 max_length表示字符长度 |
IntegerField() | 一个整数类型 范围在 -2147483648 to 2147483647 (一般不用它来存手机号(位数也不够) 直接用字符串存) |
BigIntegerField() | 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 |
DateField() | 日期字段 日期格式 YYYY-MM-DD 相当于Python中的datetime.date()实例 |
DateTimeField() | 日期时间字段 格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 相当于Python中的datetime.datetime()实例 |
DecimalField() | 10进制小数 参数 max_digits 小数总长度 decimal_places,小数位长度 |
EmailField() | 字符串类型 Django Admin以及ModelForm中提供验证机制 |
BooleanField() | 布尔值类型 传布尔值存数字0或1 |
TextField() | 文本类型 存储大段文本 |
FileField() | 字符串 路径保存在数据库 文件上传到指定目录 参数 upload_to = " " 上传文件的保存路径 storage = None 存储组件 默认django.core.files.storage.FileSystemStorage |
ForeignKey() | 外键类型在ORM中用来表示外键关联关系 一般把ForeignKey字段设置在 '一对多’中’多’的一方 ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系 |
OneToOneField() | 一对一字段 通常一对一字段用来扩展已有字段 通俗的说就是一个人的所有信息不是放在一张表里面的,简单的信息一张表,隐私的信息另一张表,之间通过一对一外键关联 |
ManyToManyField() | 简单来说就是在多对多表关系并且这一张多对多的关系表是有Django自动帮你建的情况下 下面的方法才可使用create add set remove clear |
2、自定义字段类型
ORM支持用户自定义字段类型,比方说ORM中没有设置char类型的字段,我们可以使用自定义字段来实现他。
方法
class MyCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
uper().__init__(max_length=max_length, *args, **kwargs)
def db_type(self, connection):
return 'char(%s)' % self.max_length
# 这里是调用我们定义的字段类型
class User(models.Model):
name = models.CharField(max_length=32)
info = MyCharField(max_length=64)
七、ORM常用字段参数
名称 | 含义 |
---|---|
primary_key | 主键 |
verbose_name | 注释 |
max_length | 字段长度 |
max_digits | 小数总共多少位 |
decimal_places | 小数点后面的位数 |
auto_now | 每次操作数据自动更新事件 |
auto_now_add | 首次创建自动更新事件后续不自动更新 |
null | 允许字段为空 |
default | 字段默认值 |
unique | 唯一值 |
db_index | 给字段添加索引 |
choices | 当某个字段的可能性能够被列举完全的情况下使用。如:性别、学历、工作状态、... |
to | 关联表 |
to_field | 关联字段(不写默认关联数据主键) |
on_delete | 当删除关联表中的数据时,当前表与其关联的行的行为。 |
on_delete
当两张连表进行关联后,主表的数据被删除时,从表中对应的数据正在默认情况下也会被删除,但是on_delete可以设置默认值,当主表数据被删除时,从表中对应的数据会被修改为默认值
def func():
return 10
class MyModel(models.Model):
user = models.ForeignKey(
to="User",
to_field="id",
on_delete=models.SET(func)
)
# on_delete可以设置默认值,当主表数据被删除时,从表中对应的数据会被修改为默认值
不同值对应的功能:
1、models.CASCADE
级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2、models.SET_NULL
当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
3、models.PROTECT
当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
4、models.SET_DEFAULT
当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
5、models.SET()
当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
6、models.DO_NOTHING
什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
choices
当字段数据的可能性是可以完全列举出来的时候 应该考虑使用该参数
- get_gender_display()
- 获取choices参数内的数据值
class UserInfo(models.Model):
username = models.CharField(max_length=32)
gender_choice = (
(1, '男性'),
(2, '女性'),
(3, 'other'),
)
gender = models.IntegerField(choices=gender_choice)
user_obj = models.UserInfo.objects.filter(pk=1).first()
print(user_obj.gender) # 获取的是真实数据
print(user_obj.get_gender_display())
user_obj1 = models.UserInfo.objects.filter(pk=2).first()
user_obj2 = models.UserInfo.objects.filter(pk=3).first()
user_obj3 = models.UserInfo.objects.filter(pk=4).first()
print(user_obj1.get_gender_display())
print(user_obj2.get_gender_display())
print(user_obj3.get_gender_display()) # 如果没有则按照真实数据返回
Django框架:8、聚合查询、分组查询、F与Q查询、ORM查询优化、ORM事务操作、ORM常用字段类型、ORM常用字段参数的更多相关文章
- Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)
Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...
- Django模型系统——ORM中跨表、聚合、分组、F、Q
核心知识点: 1.明白表之间的关系 2.根据关联字段确定正反向,选择一种方式 在Django的ORM种,查询既可以通过查询的方向分为正向查询和反向查询,也可以通过不同的对象分为对象查询和Queryse ...
- Django框架08 /聚合查询、分组、F/Q查询、原生sql相关
Django框架08 /聚合查询.分组.F/Q查询.原生sql相关 目录 Django框架08 /聚合查询.分组.F/Q查询.原生sql相关 1. 聚合查询 2. 分组 3. F查询和Q查询 4. o ...
- Django orm进阶查询(聚合、分组、F查询、Q查询)、常见字段、查询优化及事务操作
Django orm进阶查询(聚合.分组.F查询.Q查询).常见字段.查询优化及事务操作 聚合查询 记住用到关键字aggregate然后还有几个常用的聚合函数就好了 from django.db.mo ...
- Django 聚合查询 分组查询 F与Q查询
一.聚合查询 需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg 关键语法:aggregate(聚合结果别名 = 聚合函数(参数 ...
- Django 聚合分组F与Q查询及choices
一.聚合查询 需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg 关键语法:aggregate(聚合结果别名 = 聚合函数(参数 ...
- Django中多表的增删改查操作及聚合查询、F、Q查询
一.创建表 创建四个表:书籍,出版社,作者,作者详细信息 四个表之间关系:书籍和作者多对多,作者和作者详细信息一对一,出版社和书籍一对多 创建一对一的关系:OneToOne("要绑定关系的表 ...
- django----聚合查询 分组 F与Q查询 字段 及其 参数
目录 一.orm补充查询 聚合查询 1-1 分组查询 1-2 F与Q查询 1-3 二. 字段及其参数 常用字段 AutoField IntegerField CharField DateField D ...
- django基础之day05,F与Q查询,Q查询的高级用法
#F与Q查询 #*************************** F 查询 ******************** # F 查询数据库中的其他字段!!! #1.查询库存数大于卖出数的书籍 fr ...
- django F与Q查询 事务 only与defer
F与Q 查询 class Product(models.Model): name = models.CharField(max_length=32) #都是类实例化出来的对象 price = mode ...
随机推荐
- Java(15)Object类
前言 Object类是Java中所有类的始祖,在Java中每个类都扩展了Object.如果没有明确地指出超类,Object就被认为是这个类的超类.由于在Java中每个类都是由Object类扩展而来的, ...
- Codeforces Round #709 Div2
就ac了一题.QAQ掉分了我好难过. A题要画图推出来公式. B不会,现在没看到好懂得题解. C题,思路错了,给一些数,每天只能选其中一些,每个数不能被选超过k次,应该先将每天只能选一个得这个数先选上 ...
- uoj316【NOI2017】泳池
题目链接 \(S=k\)可以拆成\(S\le k\)减去\(S\le k-1\).用\((i,j)\)表示第i行第j列. 设\(g(i,j)\)表示前i行前j列都安全其他未知满足条件的概率,\(h(i ...
- Unexpected token u in JSON at position 0
文章目录 1.1 错误原因: 1.2 解决思路: 1.1 错误原因: 因为JSON.parse()不能解析字符串中的undefined 出错的结果:某一行的这个字段的值为空,就会报错,整个表格都显示不 ...
- 齐博x1页面报数据表错误如何修复
如果服务器突然重启,很容易导致数据表损坏,那是因为有用户正在读取数据表,但服务器突然中断服务,就会报下类下面的错误. 大家凡是看到类似下面的错误,包含关键字 Table *** is marked a ...
- golang中的字符串
0.1.索引 https://waterflow.link/articles/1666449874974 1.字符串编码 在go中rune是一个unicode编码点. 我们都知道UTF-8将字符编码为 ...
- 亚马逊云 RDB数据故障转移(多可用区)
RDB关系数据库(Relational Database,RDB) 创建名为VPC for RDS的vpc 两个可用区,两组公内网 创建安全组 创建RDS数据库实例用的数据库子网组 创建RDS数据库实 ...
- Windows下pip换成清华源
1.在C:\Users\用户名\ 下创建 pip 文件夹2.在文件夹内创建pip.ini 文件, 添加如下内容: [global] timeout = 6000 index-url = https:/ ...
- Django Admin save 重写 保存
在 django admin管理控制台中,用户按下"Save and add another",表单的字段值仍然填充最后插入的值 并且保存 在ModelAdmin中添加选项save ...
- 长事务 (Long Transactions)
长事务 长事务用于支持 AutoCAD 参照编辑功能,对于 ObjectARX 应用程序非常有用.这些类和函数为应用程序提供了一种方案,用于签出实体以进行编辑并将其签回其原始位置.此操作会将原始对象替 ...