乐趣区

关于python:Django笔记二十四之数据库函数之比较和转换函数

这一篇笔记开始介绍几种数据库函数,以下是几种函数及其作用

  1. Cast 转换类型
  2. Coalesce 优先取值
  3. Greatest 返回较大值
  4. 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 笔记。

原文链接:Django 笔记二十四之数据库函数之比拟和转换函数

如果想获取更多相干文章,可扫码关注浏览:

退出移动版