Django中models.TextChoices与models.IntegerChoices的区别及选型指南
两段代码的核心区别
两段代码都是Django的枚举类定义,核心差异是存储值的类型:
# Code 1 文本枚举 class YearInSchool(models.TextChoices): FRESHMAN = 'FR', _('Freshman') SOPHOMORE = 'SO', _('Sophomore') JUNIOR = 'JR', _('Junior') SENIOR = 'SR', _('Senior') GRADUATE = 'GR', _('Graduate')
继承自models.TextChoices,每个枚举的实际存储值是短字符串,搭配模型字段用CharField(max_length=2)即可。
# Code 2 整数枚举 class YearInSchool(models.IntegerChoices): FRESHMAN = 1, _('Freshman') SOPHOMORE = 2, _('Sophomore') JUNIOR = 3, _('Junior') SENIOR = 4, _('Senior') GRADUATE = 5, _('Graduate')
继承自models.IntegerChoices,每个枚举的实际存储值是整数,搭配模型字段常用PositiveSmallIntegerField。
为什么开发者更偏好TextChoices
首先你提到的「IntegerChoices搭配PositiveSmallIntegerField占用内存更小」其实是个认知误区:长度为2的CharField在绝大多数数据库中占用2字节存储空间,和PositiveSmallIntegerField的存储占用完全一致,两者的内存/存储成本几乎没有差异。
开发者偏好文本枚举的核心原因有几个:
- 可读性极高:直接查询数据库时,看到
FR就能立刻对应到大一,看到1还需要翻代码找枚举的映射关系,排查问题、写原生SQL的效率高很多,尤其是维护老项目或者跨团队协作时,不需要额外同步枚举映射规则。 - 使用习惯延续:Django 3.0官方才推出内置的
TextChoices和IntegerChoices,之前大家自定义枚举就普遍用文本元组的形式(('FR', 'Freshman'),...),切换到官方的TextChoices完全符合原有使用习惯,迁移成本为零。 - 扩展性更强:后续如果要新增枚举值,文本枚举不需要考虑排序问题,比如要加预科阶段,直接新增
PRE = 'PRE', _('Preparatory')即可,完全不影响已有数据;如果用整数枚举,插在最前面要么改原有所有枚举的数值,要么加个0值,很容易产生脏数据。 - 对接成本更低:和前端、第三方系统交互时,文本值本身就有语义,不需要额外做一层「数字到含义」的映射,传参、联调时不容易出错。
两者的适用场景
优先用TextChoices的场景
- 枚举值不需要参与数值计算
- 希望直接查询数据库就能看懂字段含义
- 后续可能会新增枚举值,不想修改已有数据
- 需要和外部系统频繁交互
优先用IntegerChoices的场景
- 枚举值需要参与数值运算,比如优先级、权重类的字段,需要拿值做排序、计算
- 对接的外部系统明确要求使用整数类型的枚举值
- 枚举值数量极多(上百个),确实需要压缩存储成本的极端场景
内容的提问来源于stack exchange,提问作者Ambitions
相关产品推荐
相关产品推荐

