Django的日常-模型层(2)

几种常用的查询方式

聚合查询

​ 聚合,我们应该有这个概念,因为在数据库的SQL语言里面有聚合函数的概念,聚合,字面意思来说,就是把一类东西放在一起,但是跟分组又不太一样.

​ 我们知道我们在写SQL语句的时候,分组groupby和聚合函数是分不开的,因为一旦select语句里面有分组,那么我们就只能查询到分组依据的字段以及一些聚合函数组成的字段,别的字段写在select后面会报错的.

​ 所以,既然ORM是用来操作数据库的,那么我们在使用聚合查询的时候,就要遵循这个规律.聚合查询的具体用法如下:

# 首先导入聚合函数,聚合函数的关键字为aggregate
from django.db.models import Max,Min,Sum,Count,Avg # 大概格式为:models.表名.objects.查询方式(匹配条件).aggregate(聚合函数(表中的字段))
res = models.Book.objects.all().aggregate(Avg('price'))
print(res)

分组查询

​ 分组查询的关键字为annotate,使用起来非常的简单,实际在数据库里的操作其实就是groupby,分组查询会按照models后面的表名来分组,然后在后面括号内对分组后的数据进行操作

# 分组查询的格式为:models.表名.objects.annotate(对组内数据做操作)
res = models.Book.objects.annotate(author_number=Count('authors').values('author_num'))
print(res)

F和Q查询

​ 上面的聚合和分组查询都是我们从表中取出字段,然后与一个我们设定好的常量作比较,设想这样一种情景,如果我们需要从数据库取出来两个不同字段的值作比较,该如何实现呢?Django里面就给我们提供了F和Q查询来解决这一问题.

from django.db.models import F,Q
res = models.Book.objects.filter(sell = F('kucun'))
print(res)
# 以上语句可以实现在Book表中,我们以kucun列为依据,来查询得到自己想要的数据,甚至可以在查询的时候直接对数据做操作,比如
res = models.Book.objects.filter(sell = F('kucun')+100)
print(res) # 而Q查询比F查询更加强大,比如以下情景
# 我们需要根据不止一个条件来筛选记录,而且这些条件并不是and关系,而是or,或者not,此时就可以使用Q查询来解决问题,比如:
res = models.Book.objects.filter(Q(title='python')|Q(kucun=666))
res1 = models.Book.objects.filter(~Q(title='python')|Q(kucun=666))
print(res,res1)
# 以上两个例子,在两个Q之间用|是or的意思,即两者只要有一个成立就算符合条件,~则是取反的意思

​ Q查询还有一种更优秀的用法,我们知道Q查询其实是一个类,所以我们通过实例化产生一个对象,然后通过操作这个对象来实现Q查询以及对数据进行筛选的目的,比如

from django.db.models import Q
q = Q()
q.connector = 'or' # 这里可以直接配置其查询的方式,可以是or,可以是not
q.children.append(('title','python'))
q.children.append(('kucun',666))
res = models.Book.objects.filter(q)
print(res)

查询优化相关

​ ORM的查询优化一般会有四个比较常用的方法,他们都是成对出现,对比使用的,即only和defer,select_relater和prefetch_related,下面我们逐一介绍.

only和defer('字段')
首先他们的用法都是在关键字后面括号中加入表中有的字段.
only会将括号内字段对应的所有数据直接封装起来,然后返回给我们的对象中,因为only()最后返回的是一个对象,然后我们对这个对象来进行操作的时候,如果点出来的是之前括号内的字段,那么此次查询就不会再经过数据库,但是如果点出来是括号内不包含的字段,那么每次都会重新查询数据库.
做一个类比来说,only后面括号内字段所对应的数据相当于是拿出来放在了计算机的缓存中,我们在查询这个字段的时候就直接从缓存里取,而不需要再去查询数据库,可以节约大量查询的时间,当然这只是一个类比,实际情况并不是缓存的概念.
defer的用法就和only完全相反,defer后面括号内字段对应的数据,在每次查询的时候都需要查询数据库,而括号内不包含的字段对应的数据查询则不需要查询数据库.
个人理解only和defer的用法,only应该是用在不常修改的字段,也就是说only后面括号内的字段应该是修改次数尽量少的字段,这样既能提升效率,查询出来又不会出错.同理,defer后面括号内则是应该写频繁修改的字段,需要实时监控其变化的那种字段,比较合适.
select_relater和prefetch_related('外键关联表的表名')
首先,select_relater和prefetch_related的共同点在于其传参的规则是相同的,其后面的括号里面都只能放外键字段,且只能放一对一和一对多的外键字段,不能放多对多的字段,而且可以叠加,即可以select_related(外键字段__外键字段__外键字段)这样放.
select_related会自动帮我们做连表操作,这些表必须是有外键相关联的,select_related将连表之后的数据全部查询出来,然后封装起来,传给对象.
而prefetch_related看似也是一个连表操作,其实不是,prefetch_related实际上是一种类似子查询的存在,其会多次查询不同的表,然后把最后的结果返回出来.
这两种方法的区别在于
第一种,内部自动连表,消耗的资源和时间都在连表上,对数据库的操作比较少,数据库压力小
第二种,内部不做连表,消耗的资源和时间都在对数据库的查询上,数据库压力较大,但是整体效率较高

orm中常见字段

​ ORM中的字段就是我们在models.py里面定义表类型的时候,对于字段的定义所用的格式,常用的有以下几种:

# 自增的数字,常用来设置主键,primary_key = True就为主键
AutoField(primary_key = True) # 最常用的字符类型,相当于python中的varchar,max_length为其最大长度,超过这个长度的会被舍弃
CharField(max_length=32) # 整型,默认括号内为空
IntegerField() # 时间格式,常用参数有两个:
DateField()
auto_now:每次对对象进行操作都会更新当前时间
auto_now_add:在创建或添加对象的时候会添加这个时间,然后不会改变
# 小数格式的数字,max_digits为数字的总位数,decimal_places为数字的小数的位数
DecimalField(max_digits=8,decimal_places=2)
# 布尔类型,存储到数据库中的时候是0/1,并不是True和False
BooleanField()

choices参数

choices参数通常是IntegerField中的参数,因为我们市场希望的是用简单的数字来代替不同的意思,或者选项,比如我们在定义一个类中字段的是时候,该字段要显示用户的性别,我们可以这么写:

# models.py
choices = (
(1,'male'),
(2,'female'),
(3,'guess')
) sex = models.IntegerField(choices=choices)
# 以上这种操作就可以实现我们的需求,在后端向前端传送数据的时候只需要传1,2,3就可以了,大大减少了传送数据的量级

这种使用方式可以简化传送数据的大小,但是在取数据的时候也和原来有些区别,并不是直接用点的形式来取数据了.

from app01 import models
user_obj = models.Userinfo.objects.filter(pk=1),first()
res = user_obj.get_gender_display()
print(res)
# 其取值方式为固定句式,即
# 数据对象.get_字段名_display()
# 注意,如果数字没有对应关系的话,该种方式取出来的还是这个数字,并不会报错

orm的事务操作

​ 我们知道数据库中有事务,事务的四大特点ACID为

  1. 原子性

  2. 一致性

  3. 隔离性

  4. 持久性

    所以我们在ORM中也需要有事务的存在.具体操作如下

from django.db import transaction
with transaction.atomic()
#这里写的所有ORM语句都属于同一个事务
# 事务的结束标志就是这一个缩进

Django的日常-模型层(2)的更多相关文章

  1. Django的日常-模型层(1)

    目录 Django的日常-模型层(1) 模型层 django测试环境 ORM查询 Django的日常-模型层(1) 模型层 模型层其实就是我们应用名下的models.py文件,我们在里面写入想要创建的 ...

  2. Django的日常-路由层

    目录 Django的日常-2 路由层 有名分组和无名分组 反向解析 路由的分发 Django的日常-2 路由层 我们之前已经接触过路由层,只是我们可能不知道他叫这个名字,实际上在Django里面路由层 ...

  3. Django学习之模型层

    模型层 查看orm内部sql语句的方法的方法 1.如果是queryset对象,那么可以点query直接查看该queryset的内部sql语句 2.在Django项目的配置文件中,配置一下参数即可实现所 ...

  4. Django基础之模型层(02)

    1 重要概念 # 多表查询 """ 正向查询 反向查询 当前查询对象是否含有外键字段 如果有就是正向 没有无则是反向 口诀: 正向查询按外键字段 多对多需要额外再加一个. ...

  5. Django基础(3)----模型层-单表操作,多表创建

    昨日内容回顾: 1. {% include '' %} 2. extend base.html: <html> ..... ..... ..... {% block content%} { ...

  6. Django基础之模型层(下)

    聚合查询 关键字:aggregate from django.db.models import Max,Min,Sum,Count,Avg 统计所有书的平均价格 models.Book.objects ...

  7. Django基础之模型层(01)

    内容概要 查询关键字 MySQL select    from    where    group by    having    order by    distinct    limit    r ...

  8. Django模型层ORM学习笔记

    一. 铺垫 1. 连接Django自带数据库sqlite3 之前提到过Django自带一个叫做sqlite3的小型数据库,当我们做本地测试时,可以直接在sqlite3上测试.不过该数据库是小型的,在有 ...

  9. 64、django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

随机推荐

  1. delphi xe10 手机内部系统相关操作(手机信息、震动、剪贴板、键盘、电话、拨号)

    //获取手机信息 function GetPhoneInfo(): string; Var TelephonyManager: JTelephonyManager; TelephonyServiceN ...

  2. 基于bootstrap的时间选择插件daterangepicker以及汉化方法

    双日历时间段选择插件 — daterangepicker是bootstrap框架后期的一个时间控件: 可以设定多个时间段选项:也可以自定义时间段:由用户自己选择起始时间和终止时间:时间段的最大跨度可以 ...

  3. 其它课程中的python---4、Matplotlib最最最最简单使用

    其它课程中的python---4.Matplotlib最最最最简单使用 一.总结 一句话总结: 慢慢来吧,不着急,心态平和和沉稳:每次和世界交互,你就能感受到无比的自信 1.如何区别python2和p ...

  4. LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)

    题目标签:Math 题目让我们判断机器人是否是一直在走一个圈. 当我们把 instructions 走完一遍时候: 1. 如果机器人回到了原点,那么它是在走一个圈. 2. 如果机器人的方向没有改变,那 ...

  5. 简单实用的makefile

    简单的makefile 为了说明问题,就新建一组文件如下: 文件布局及运行结果: make clean 按目录归置 文件看起来是是清楚了,但是makefile写得揪心. 实用版 (1)Makefile ...

  6. Codeforces 1168A Increasing by Modulo

    题目链接:http://codeforces.com/problemset/problem/1168/A 题意:给一个数组,数组中元素范围为0~n,每次你可以选择若干元素进行(ai+1)%m的操作,问 ...

  7. mysql的JDBC连接

    程序是通过DriverManager注册驱动,所以加载之后可以直接使用DriverMannagermysql中的多态: 不仅是赋值的时候使用了多态,返回的时候都是返回的借口(不是返回的子类对象),所以 ...

  8. postgres优化项及linux上pg操作记录

    1.linux切换到pg命令: $ su - postgres $ psql postgres=# 2.查看/退出pg ps -ef |grep postgres postgres=# \q 3.一般 ...

  9. Python服务端工程师就业面试指导✍✍✍

    Python服务端工程师就业面试指导  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的时 ...

  10. JS对象 向下取整floor() floor() 方法可对一个数进行向下取整。 语法: Math.floor(x)

    向下取整floor() floor() 方法可对一个数进行向下取整. 语法: Math.floor(x) 参数说明: 注意:返回的是小于或等于x,并且与 x 最接近的整数. 我们将在不同的数字上使用 ...