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
相关产品推荐
相关产品推荐

