Django ORM实现查询取整/保留小数/自定义函数,Fun类(一般用于聚合函数)

Django ORM实现查询取整/保留小数/自定义函数,Fun类(一般用于聚合函数)

1. 需求分析

最近做的项目中,想到对查询结果集用一个取整,比如下面的数据

表Data

idvalue
9998185.54871
9999941.12546

因为Django本身并没有带取整函数,所以一般情况下我们都这样实现取整

result = int(Data.objects.get(id=9998).value)

当然,也会这样保留小数

result_round = round(Data.objects.get(id=9998).value,2)

但是如果查询很多结果,或者说通过分组查询,返回的是一个dict,这样取整就还要自己写一次for循环,而且不如让他直接在SQL查询的时候就取整,而且SQL本身也是有取整和保留小数的函数的。

下面就是,用SQL实现保留两位小数

select Round(value,2) from DATA

比如下面这种,用的.values(),返回的是一个dict

queryset_dict = queryset.values(
    name=F('city__label')).annotate(
    value=Avg((F('min_salary') + F('max_salary')) / 2)
)

-> [{"name":"xxxx","value":xxxx.xxx}]
# 所以,再写个for循环取整太麻烦

2. 需求实现

经常用法1 - 继承内置Func类

Func类,是Django ORM提供的用于自定义函数的类,我们可以让函数继承自Func,自定义查询方法

下面就来定义一个Round函数

from django.db import models

class Floor(models.Func):
    """
        Django ORM自定义Floor方法,用于取整,就是数据库中的Floor函数
    """
    function = 'FLOOR'
    # 定义用SQL中的哪个函数
    template = '%(function)s(%(expressions)s)'
	# 定义SQL语句模板
	# %(function)s -> 定义的function
	# %(expressions)s -> 实例化时传入的数据
    output_field = models.IntegerField()
    # 字段类型,注意要带括号,必须是实例化对象
    
# -------实现ROUND保留两位小数----------
class Round(models.Func):
    """
        Django ORM自定义Floor方法,用于取整,就是数据库中的Floor函数
    """
    function = 'ROUND'
    # 定义用SQL中的哪个函数
    template = '%(function)s(%(expressions)s,2)'
	# 定义SQL语句模板
	# %(function)s -> 定义的function
	# %(expressions)s -> 实例化时传入的数据
    output_field = models.FloatField()
    # 字段类型,注意要带括号,必须是实例化对象

实际使用

queryset_dict = queryset.values(
    name=F('city__label')).annotate(
    value=Floor(Avg((F('min_salary') + F('max_salary')) / 2))
    # 在这里,直接在聚合Avg后,再调用Floor,就可以取整
)

临时用法2 - 实例化Func传入

上面的用法,总是需要我们定义一个类,但是我们有时候只是想简单用一次,可以直接实例化传入

queryset_dict = queryset.values(
    name=F('city__label')).annotate(
    value=models.Func(
        Avg((F('min_salary') + F('max_salary')) / 2),
    	function='Floor'
    	)
    	# template默认就是%(function)s(%(expressions)s)所以这里不传入
    )
### 如果用round并且指定保留两位则需要传入template
models.Func(
        数据,
    	function='Round',
    	template='%(function)s(%(expressions)s,2)'
    	)

当然,我们也可以继承Func并重写__init__实现更定制化的自定义(这里不额外讲解,就是面向对象基础)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值