You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Django Transform实现字符串转Int/Null时遇AttributeError求助

解决Django自定义as_int Transform的AttributeError问题

错误根源是你在When条件中误用了Regex(这是查询用的Lookup类,而非表达式函数),传入self.lhs(Col对象)时触发了字符串分割逻辑的错误。以下是修正后的代码:

from django.db.models import Case, Cast, Value, When
from django.db.models.functions import RegexpMatches
from django.db.models.lookups import Transform
from django.db import models

class AsIntTransform(Transform):
    lookup_name = "as_int"
    output_field = models.IntegerField()

    def as_sql(self, compiler, connection):
        # 使用RegexpMatches函数执行正则匹配(Django 3.2+支持)
        case_expr = Case(
            When(
                RegexpMatches(self.lhs, r"^\d+$"),
                then=Cast(self.lhs, models.IntegerField()),
            ),
            default=Value(None),
            output_field=models.IntegerField(),
        )
        sql, params = case_expr.as_sql(compiler, connection)
        return sql, params

models.CharField.register_lookup(AsIntTransform)
models.TextField.register_lookup(AsIntTransform)

核心修改说明:

  • 替换Regex为RegexpMatches:Regex是用于查询的Lookup类(如field__regex=r'...'),而RegexpMatches是数据库函数表达式,能正确处理self.lhs(Col对象)。
  • 给Case指定output_field:明确输出类型,避免潜在的类型推断异常。

若你的Django版本低于3.2,可手动用Func构建数据库特定的正则匹配逻辑:

# 以MySQL为例(PostgreSQL需将function改为'~')
from django.db.models import Func

# 替换原RegexpMatches行:
Func(self.lhs, Value(r"^\d+$"), function='REGEXP')

测试你的查询逻辑:

Comment.objects.filter(body__as_int__gt=5)

此时body为"37"的记录会被转为整数37参与比较,非纯数字内容会被视为NULL,不会被纳入结果(NULL与任何值比较均返回NULL,不满足gt=5的条件)。

内容的提问来源于stack exchange,提问作者Daniel Gordos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:12:42