Django是否支持类似models.TextChoices的模型字段整数枚举?
Django 整数枚举类型实现方案
Django 3.0及以上版本原生提供了开箱即用的IntegerChoices整数枚举类,完全适配你当前使用的Django 3.2版本,无需额外引入第三方依赖。
修改后的模型代码
import uuid from datetime import datetime from django.db import models from django.utils.translation import gettext_lazy as _ class Transaction(models.Model): class TransactionTypes(models.IntegerChoices): # 枚举值改为整数,第二个参数依然是对外展示的可读文本 BUY = 1, _('买入') SELL = 2, _('卖出') id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) created = models.DateTimeField(null=False, default=datetime.now) price = models.FloatField(null=False) amount = models.FloatField(null=False) # 字段类型替换为SmallIntegerField,占用空间更小 type = models.SmallIntegerField( null=False, choices=TransactionTypes.choices, # 建议添加默认值,避免迁移过程中出现无值报错 default=TransactionTypes.BUY ) class Meta: indexes = [ models.Index(fields=['created']), ]
方案优势
- 存储效率更高:
SmallIntegerField仅占用2字节存储空间,远小于之前长度为5的CharField,枚举值数量不超过32767的场景完全够用,即使后续扩展更多枚举值,最多也仅需要使用占4字节的IntegerField,存储效率远高于字符类型 - 使用逻辑完全兼容:依然可以直接通过
TransactionTypes.BUY的方式赋值、做判断,模板、序列化层也能正常获取枚举对应的可读文本,和之前TextChoices的使用方式没有差异 - 查询性能更好:整数的比对、索引效率远高于字符串,涉及
type字段的过滤、排序操作性能会有明显提升
存量数据迁移注意事项
如果当前Transaction表已经存在存量数据,需要先完成数据映射再修改字段类型,避免迁移报错:
- 先编写自定义迁移脚本,将原有字符类型的
type值做映射:BUY对应1、SELL对应2 - 先在测试环境验证数据映射、字段类型修改逻辑无误后,再操作生产环境数据
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

