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

Django对接MySQL设置enum数据类型出现SQL语法错误问题求助

错误原因

你当前的报错是因为自定义EnumField的db_type方法仅返回了enum字符串,没有按照MySQL/MariaDB的语法要求拼接枚举值列表,导致生成的建表SQL中字段类型为非法的enum NOT NULL,触发语法错误。

修复方案

1. 完善自定义EnumField实现

直接在你的模型层定义如下EnumField,支持传入枚举值列表和默认值参数,自动生成符合要求的数据库类型:

from django.db.models import CharField

class EnumField(CharField):
    # 新增自定义参数:enum_values为逗号分隔的枚举值字符串,default为字段默认值
    def __init__(self, enum_values=None, default=None, *args, **kwargs):
        self.enum_values = enum_values
        self.default = default
        # 兼容原有choices参数逻辑,如果没传enum_values则从choices提取枚举值
        if not self.enum_values and kwargs.get('choices'):
            # 自动转义枚举值中的单引号避免SQL语法错误
            self.enum_values = ",".join([f"'{v[0].replace(\"'\", \"''\")}'" for v in kwargs['choices']])
        super().__init__(*args, **kwargs)

    def db_type(self, connection):
        # 拼接符合MySQL要求的enum类型语法
        base_type = f"enum({self.enum_values})"
        if self.default:
            base_type += f" DEFAULT '{self.default.replace(\"'\", \"''\")}'"
        return base_type

2. 修改模型类调用

两种调用方式二选一即可:

class tblusertokens(models.Model):
    token_id = AutoField(primary_key=True)
    # 方式1:直接用已有的choices参数,自动提取枚举值
    token_type = EnumField(choices=enumTokenTypes.choices, default=enumTokenTypes.Registration, max_length=20)
    # 方式2:手动传逗号分隔的枚举值
    # token_type = EnumField(enum_values="'Registration','Forgot Password'", default="Registration", max_length=20)
    created_at = DateTimeField(auto_now_add=True, blank=True)
    user = ForeignKey(tblusers, on_delete = models.CASCADE)    

3. 迁移操作

删除之前手动修改过的异常迁移文件,重新执行python manage.py makemigrations和python manage.py migrate即可,不需要手动修改迁移文件内容。

注意事项

  • 枚举值中如果包含单引号会自动转义,无需额外处理
  • 生产环境使用前建议先在测试库验证生成的SQL语句符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 10:39:04