Django的日常-模型层(2)
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为
原子性
一致性
隔离性
持久性
所以我们在ORM中也需要有事务的存在.具体操作如下
from django.db import transaction
with transaction.atomic()
	#这里写的所有ORM语句都属于同一个事务
# 事务的结束标志就是这一个缩进
												
											Django的日常-模型层(2)的更多相关文章
- Django的日常-模型层(1)
		
目录 Django的日常-模型层(1) 模型层 django测试环境 ORM查询 Django的日常-模型层(1) 模型层 模型层其实就是我们应用名下的models.py文件,我们在里面写入想要创建的 ...
 - Django的日常-路由层
		
目录 Django的日常-2 路由层 有名分组和无名分组 反向解析 路由的分发 Django的日常-2 路由层 我们之前已经接触过路由层,只是我们可能不知道他叫这个名字,实际上在Django里面路由层 ...
 - Django学习之模型层
		
模型层 查看orm内部sql语句的方法的方法 1.如果是queryset对象,那么可以点query直接查看该queryset的内部sql语句 2.在Django项目的配置文件中,配置一下参数即可实现所 ...
 - Django基础之模型层(02)
		
1 重要概念 # 多表查询 """ 正向查询 反向查询 当前查询对象是否含有外键字段 如果有就是正向 没有无则是反向 口诀: 正向查询按外键字段 多对多需要额外再加一个. ...
 - Django基础(3)----模型层-单表操作,多表创建
		
昨日内容回顾: 1. {% include '' %} 2. extend base.html: <html> ..... ..... ..... {% block content%} { ...
 - Django基础之模型层(下)
		
聚合查询 关键字:aggregate from django.db.models import Max,Min,Sum,Count,Avg 统计所有书的平均价格 models.Book.objects ...
 - Django基础之模型层(01)
		
内容概要 查询关键字 MySQL select from where group by having order by distinct limit r ...
 - Django模型层ORM学习笔记
		
一. 铺垫 1. 连接Django自带数据库sqlite3 之前提到过Django自带一个叫做sqlite3的小型数据库,当我们做本地测试时,可以直接在sqlite3上测试.不过该数据库是小型的,在有 ...
 - 64、django之模型层(model)--建表、查询、删除基础
		
要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...
 
随机推荐
- 线性基算贡献——19牛客多校第一场H
			
/* 给定数组a[],求有多少集合的异或值为0,将这些集合的大小之和求出来 对于每个数来说,如果除去这个数后数组里做出的线性基和这个数线性相关,那么这个数贡献就是2^(n-1-线性基的大小) 反之这个 ...
 - 反演+分块套分块——bzoj2154
			
题解都在论文里了 #include<bits/stdc++.h> using namespace std; #define maxn 10000005 #define ll long lo ...
 - [NOI.AC] palindrome
			
思路: \(50pts\) \(f[l,r]\)表示区间\([l,r]\)能够变成多少个串,转移枚举\(l\),利用\(hash\)判字符串相等. 复杂度\(O(Tn^3)\) \(70pts\) 考 ...
 - WinDbg解决BHO不加载
			
昨天zhengwei同学说他机器上的一个BHO不能正常加载,我把BHO的代码拿过来,在我的两台机器上都验证了一下,一台是Win7+IE8的环境,一台是XP+IE7的环境,都能正常加载.zhengwei ...
 - 数据结构C++版-线性表
			
PS:资料来源慕课网视频. 一.什么是线性表 线性表是n个数据元素的有限序列. 分类: 二.补充知识点 1.栈和队列有出操作.入操作,对应线性表(数组)为插入元素和删除元素,而线性表中要获取指定元素值 ...
 - 使用Docker创建数据容器
			
使用Docker创建数据容器 翻译自: Data-only container madness 1.什么是数据容器? 数据容器就是本身只创建一个volume供其他容器共享,创建完后即退出,不执行任何任 ...
 - ZK4字命令
			
zookeeper4字命令:两种方式,1.通过telnet链接服务器,执行stat.2.echo stat|nc xxx.xxx.xxx.xxx 2181效果是一样的conf:zk服务器运行时的基本信 ...
 - HDU1501-Zipper-字符串的dfs
			
Given three strings, you are to determine whether the third string can be formed by combining the ch ...
 - Python3 From Zero——{最初的意识:003~数字、日期、时间}
			
一.对数值进行取整:round(value,ndigits) >>> round(15.5,-1) #可以取负数 20.0 >>> round(15.5,0) #当 ...
 - 剑指offer——30包含min函数的栈
			
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 题解: 借助辅助栈,新的数据<=f辅助栈顶时,就压入辅助栈,这样,就能保证辅 ...