Django笔记二十四之数据库函数之比较和转换函数
本文首发于公众号:Hunter后端
原文链接:Django笔记二十四之数据库函数之比较和转换函数
这一篇笔记开始介绍几种数据库函数,以下是几种函数及其作用
- Cast 转换类型
- Coalesce 优先取值
- Greatest 返回较大值
- Nullif 值相同返回 None
1、model 准备
这一篇笔记我们主要用到 Author 和 Entry model 作为示例,下面的是 Author model:
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField(null=True, default=None)
age = models.IntegerField(null=True, blank=True)
alias = models.CharField(max_length=50, null=True, blank=True)
goes_by = models.CharField(max_length=50, null=True, blank=True)
一般来说,对于 CharField 字段,我们是不推荐允许 null=True 存在的,因为这样的话,在数据库中就会存在两个空值,一个是 null,一个是空字符串 ''。
在这里允许这样操作是为了方便的介绍下面的功能。
注意下,数据库相关函数都是在 django.db.models.functions 模块下
2、Cast 转换类型
Cast 的作用,我们可以将其理解成转换数据类型,比如在 Author 中,age 字段是一个 Integer 数据。
但是如果我们想要获取数据的时候想要将其直接变成浮点型数据,就可以使用 Cast() 函数,通过 output_field=FloatField() 参数来指定输出类型。
# 先创建数据
from blog.models import Author
Author.objects.create(name='hunter', age=25)
返回一个新字段,通过 Cast() 函数来指定输出类型:
from django.db.models import FloatField
from django.db.models.functions import Cast
author = Author.objects.annotate(float_age=Cast('age', output_field=FloatField())).get(id=1)
print(author.float_age)
最后的输出就是一个浮点型数据了。
3、Coalesce 优先取值
Coalesce 的单词的含义是 合并、联合,但是在这里函数表现出的意义是,优先取值。
Coalesce() 接受多个字段或者表达式作为参数,至少为两个字段名称,然后会返回第一个非 null 的字段的值(注意: 空字符串 '' 不被认为是 null 值)
每个元素都必须是相似的类型,否则会引起报错。
对于 Author 这个model,我们想要按照 alias, goes_by, name 三个字段的这个顺序来取值。
也就是说 有alias 字段就取 alias 的内容,否则取 goes_by 的字段值,goes_by 也没有 就取 name 字段,这种情况就可以使用 Coalesce() 来操作。
先来创建几条数据:
Author.objects.create(alias="alias-1", goes_by='goes-by-1', name='name-1')
Author.objects.create(goes_by='goes-by-2', name='name-2')
Author.objects.create(name='name-3')
Author.objects.create(alias="", goes_by='goes-by-4', name='name-4')
以上三条数据的 id 在数据库分别是 2,3,4,5
接下来可以测试一下 Coalesce() 这个函数
from django.db.models.functions import Coalesce
author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=2)
print(author.new_field)
# 输出 alias-1
author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=3)
print(author.new_field)
# 输出 goes-by-2
author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=4)
print(author.new_field)
# 输出 name-3
author = Author.objects.annotate(new_field=Coalesce('alias', 'goes_by', 'name')).get(id=5)
print(author.new_field)
# 输出 空字符串 ''
以上几个例子,我们就测试出了新建字段的取值优先顺序,以及空字符串和 null 在这个函数里的区别(会跳过值为 null 的数据,但是会取空字符串的字段值)。
空值的默认值
其实用到这里,我们可以发现这个函数的另一个用法,那就是 null 值下替换的默认值。
假设我们有一个字段,我们在取值的时候,想实现,如果该字段是 null,那么我们在取值的时候就想将其替换成另一个默认值,而不是返回 null 或者后续在内存中操作替换默认值,可以这样操作:
from django.db.models import Value
author = Author.objects.annotate(new_field=Coalesce('email', Value('xxx'))).get(id=5)
print(author.new_field)
# id 等于 5 的 Author 数据,email 字段为空,所以 new_field 的值被替换成了 'xxx'
默认值的处理也可以用在聚合中,比如聚合 Sum() 的时候,如果没有满足条件的数据,聚合的结果会是一个 null,但是我们可以自动将其变为 0:
from django.db.models import Sum, Value
Author.objects.aggregate(age_sum=Coalesce(Sum('age'), Value(0)))
4、Greatest 返回较大值
Greatest() 的用法与 Coalesce 相同,接受两个或多个类型相同的元素,返回最大的一个。
可以比较数字,和时间等字段类型。
这里示例我们使用 Entry model,我们只用两个整型字段:
class Entry(models.Model):
number_of_comments = models.IntegerField()
number_of_pingbacks = models.IntegerField()
用法如下:
from blog.models import Entry
from django.db.models.functions import Greatest
Entry.objects.annotate(max_value=Greatest("number_of_comments", "number_of_pingbacks")).get(id=2).max_value
# max_value 字段取值就会是number_of_comments 和 number_of_pingbacks 之间最大的
这里我们也可以挖掘出一个骚操作,那就是取值的下限
比如这两个字段的值都没有达到我们想要的阈值,比如说是2,我们希望返回的值至少是2,可以这样设计程序:
Entry.objects.annotate(max_value=Greatest("number_of_comments", "number_of_pingbacks", Value(2))).get(id=2).max_value
注意: 在MySQL 和 Oracle 中,如果 Greatest 中,只要有一个字段值为 null,那么结果就会返回 null,这一点一定要注意
Least() 这个取的是最小值,与 Greatest 作用是相反的,但用法是一样的,不多介绍
5、Nullif 值相同返回 None
获取两个字段,也可以是表达式的结果,或者是 Value() 的值,但两者的数据类型得一致,用于判断两者的值是否相同。
如果两者的值相同,则返回 Python 里的 None,不相同的话返回第一个表达式的值
用法示例如下:
Entry.objects.annotate(new_field=NullIf("number_of_comments", "number_of_pingbacks")).get(id=1).new_field
Entry.objects.annotate(new_field=NullIf("number_of_comments", Value(2))).get(id=1).new_field
以上就是本篇笔记全部内容,下一篇将介绍数据库函数之日期函数
如果想获取更多后端相关文章,可扫码关注阅读:

Django笔记二十四之数据库函数之比较和转换函数的更多相关文章
- python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法
python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法window安装redis,下载Redis的压缩包https://git ...
- (C/C++学习笔记) 二十四. 知识补充
二十四. 知识补充 ● 子类调用父类构造函数 ※ 为什么子类要调用父类的构造函数? 因为子类继承父类,会继承到父类中的数据,所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程. ...
- python3笔记二十四:Mysql数据库操作命令
一:学习内容 Mysql操作命令:启动服务.停止服务.连接数据库.退出数据库.查看版本.显示当前时间.远程连接 数据库操作命令:创建数据库.删除数据库.切换数据库.查看当前选择的数据库 表操作命令:查 ...
- JDK源码阅读-------自学笔记(二十四)(java.util.LinkedList 再探 自定义讲解)
一.实现get方法 1.一般思维实现思路 1).将对象的值放入一个中间变量中. 2).遍历索引值,将中间量的下一个元素赋值给中间量. 3).返回中间量中的元素值. 4).示意图 get(2),传入角标 ...
- Android开发(二十四)——数据存储SharePreference、SQLite、File、ContentProvider
Android提供以下四种存储方式: SharePreference SQLite File ContentProvider Android系统中数据基本都是私有的,一般存放在“data/data/程 ...
- UI学习笔记---第十四天数据持久化
一.沙盒机制 每个应用程序位于文件系统的严格限制部分 每个应用程序只能在为该程序创建的文件系统中读取文件 每个应用程序在iOS系统内斗放在了统一的文件夹目录下 沙盘路径的位置 1. 通过Finder查 ...
- Android笔记二十四.Android基于回调的事件处理机制
假设说事件监听机制是一种托付式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器全然消失了,当用户在GUI控件上激发某个事件时,控 ...
- Java基础学习笔记二十四 MySQL安装图解
.MYSQL的安装 1.打开下载的mysql安装文件mysql-5.5.27-win32.zip,双击解压缩,运行“setup.exe”. 2.选择安装类型,有“Typical(默认)”.“Compl ...
- 论文阅读笔记二十四:Rich feature hierarchies for accurate object detection and semantic segmentation Tech report(R-CNN CVPR2014)
论文源址:http://www.cs.berkeley.edu/~rbg/#girshick2014rcnn 摘要 在PASCAL VOC数据集上,最好的方法的思路是将低级信息与较高层次的上下文信息进 ...
- Java学习笔记二十四:Java中的Object类
Java中的Object类 一:什么是Object类: Object类是所有类的父类,相当于所有类的老祖宗,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object ...
随机推荐
- 【Docker】Postgres 安装
1.docker pull postgres 2.docker run --name postgres -v /home/postgre/data:/var/lib/postgresql/data - ...
- vue echarts 多个图表自适应
<template> <div :id="id" :style="{width: `${width}`, height: `${height}`}&qu ...
- 借助5G智能网关实现无人化智慧农业应用
发展智慧农业是新时代的必由之路.依托5G+物联网技术赋能农业生产,能够实现更少的人员需求,更大面积的综合土地管理,更实时精细的生产环境监测,更智能的生产自主管控.5G技术正以其广连接.低时延的优势,助 ...
- 西电oj73题字符串处理
问题描述 有一种简单的字符串压缩算法,对于字符串中连续出现的同一个英文字符,用该字符加上连续出现的次数来表示(连续出现次数小于3时不压缩).例如,字符串aaaaabbbabaaaaaaaaaaaaab ...
- TortoiseGit自动保存用户名和密码
在使用TortoiseGit上传时,会多次提示输入用户名和密码,采用以下方法解决 1.桌面点击右键 -> 选择TortoiseGit -> 点击settings 2.点击选择Git 3.点 ...
- 后端008_配置Security登录授权过滤器
------------恢复内容开始------------ 现在我们就可以去进行springscurity的配置了.首先我们新建一个配置类.然后该类需要添加@Configuration注解,然后还要 ...
- 解决df.to_csv 时增加重复双引号的问题
df.to_csv("test.csv", sep='|',quoting=csv.QUOTE_NONE,index=False,header=True) 转载自 df.to_cs ...
- Keil Jlink没法找到STM32H750
https://www.amobbs.com/thread-5713382-1-1.html MDK使用的是5.32,jlink使用的是9.2jlink驱动使用的是6.44b 删除工程下的JLinkS ...
- angularJS依赖注入的个人理解
依赖注入:一句话 --- 没事你不要来找我,有事我会去找你. AngularJS 5个核心组件用来作为依赖注入: value factory service provider constant ...
- SpringBoot之基于idea搭建ssm(maven)
此次目标为搭建一个简单的基于springboot的ssm(spring + springmvc + mybatis)的maven项目,使用的数据库为mysql. 最终项目目录结构 创建过程 1.项目创 ...