导包
from django.db.models import Func, IntegerField

自定义 Django ORM 除法取整函数

以下提供两种自定义 Django ORM 函数的实现方案,分别实现向下取整除法和向上取整除法功能:

向下取整除法实现

class DivFloor(Func):
    """
    向下取整除法:FLOOR(numerator / denominator)
    使用示例:
    queryset.annotate(result=DivFloor(F('field1'), F('field2')))
    """
    function = 'FLOOR'
    arity = 2
    output_field = IntegerField()

    def __init__(self, numerator, denominator, **extra):
        expression = numerator / denominator
        super(DivFloor, self).__init__(expression, **extra)

向上取整除法实现

class DivCeil(Func):
    """
    向上取整除法:CEIL(numerator / denominator)
    注意:arity=1 因为参数是除法表达式整体
    """
    function = 'CEIL'
    arity = 1
    output_field = IntegerField()

    def __init__(self, numerator, denominator, **extra):
        expression = numerator / denominator
        super(DivCeil, self).__init__(expression, **extra)

安全使用建议

为防止除零错误,推荐结合 Case/When 使用:

from django.db.models import Case, When, Value

safe_div = Case(
    When(denominator=0, then=Value(0)),  # 或其他默认值
    default=DivFloor(numerator, denominator)
)

复杂表达式示例

支持在参数中使用复杂表达式:

# 计算 (field1 * field3) // field2
DivFloor(F('field1') * F('field3'), F('field2'))

# 计算 CEIL(field1 / (field2 + field3))
DivCeil(F('field1'), F('field2') + F('field3'))
#        ↑ 被除数    ↑ 除数

数据库兼容性说明

  • 该实现依赖数据库的 FLOOR 和 CEIL 函数
  • MySQL、PostgreSQL、SQLite 均支持这些函数
  • 不同数据库对除零处理可能不同,建议始终添加 Case/When 保护
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐