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()) # 如果没有则按照真实数据返回

最新文章

  1. 使用clusterprofile做聚类分析
  2. WebAPI请求
  3. 股票自用指标 boll 菜刀
  4. 【Apache运维基础(5)】Apache的Rewrite攻略(2)
  5. LeetCode Number of Islands 岛的数量(DFS,BFS)
  6. Java [Leetcode 111]Minimum Depth of Binary Tree
  7. QBoxLayout::setSizeConstraint可以固定窗口的大小,且根据内部控件所占用的位置自动调节大小
  8. ORACLE—002:Create创作型
  9. iOS解析后台返回的二进制图片
  10. 【欧拉函数】 poj 2478
  11. doubango(1)--从协议栈结构说起
  12. SpagoBi开发示例——员工离职人数统计
  13. [.NET跨平台]Jexus独立版本的便利与过程中的一些坑
  14. sonar服务搭建
  15. 如何在开发过程中获取客户端的ip呢?
  16. dom 及bom
  17. 最简单的基于FFmpeg的AVfilter样例(水印叠加)
  18. Android 通过 JNI 访问 Java 字段和方法调用
  19. Android开发之使用SwipeRefreshLayout完成下拉刷新
  20. hdu 1007 N个点中输出2点的最小距离的一半

热门文章

  1. 使用nginx部署Django静态文件配置
  2. HashMap底层原理及jdk1.8源码解读
  3. ImGUI 1.87 绘制D3D外部菜单
  4. DVWA File Upload level high 通关
  5. CentOS6/7开机启动配置
  6. iframe的简单使用
  7. IP分类与子网划分
  8. Java开发学习(四十)----MyBatisPlus入门案例与简介
  9. vue传值
  10. 【深入浅出 Yarn 架构与实现】2-1 Yarn 基础库概述