如何让Django TextChoices字段接受POST请求传入的人类可读值?
实现方案
有两种常用的实现方式,可以让DRF序列化器同时支持TextChoices的存储值和可读值作为入参:
方案1:自定义通用Choice字段(推荐)
该方案可复用性高,兼容原有传存储值的逻辑,无需修改现有业务代码:
- 首先定义自定义字段:
from rest_framework import serializers class ReadableChoiceField(serializers.ChoiceField): def to_internal_value(self, data): # 优先匹配存储值,兼容旧逻辑 if data in self.choices: return data # 反向匹配可读标签 for storage_val, label in self.choices.items(): if label == data: return storage_val # 匹配失败抛出默认校验错误 self.fail('invalid_choice', input=data)
- 在序列化器中替换原有字段即可:
class MyModelSerializer(serializers.ModelSerializer): animal = ReadableChoiceField(choices=MyModel.Animals.choices) class Meta: model = MyModel fields = "__all__"
方案2:重写单字段校验逻辑
如果仅需要在单个序列化器中临时使用,可直接重写字段校验方法:
class MyModelSerializer(serializers.ModelSerializer): class Meta: model = MyModel fields = "__all__" def validate_animal(self, value): # 校验是否为合法存储值 if value in MyModel.Animals.values: return value # 反向匹配可读标签 for enum_item in MyModel.Animals: if enum_item.label == value: return enum_item.value raise serializers.ValidationError(f"{value} 不是有效的动物选项")
效果说明
修改完成后,前端提交{"animal": "Coyote"}或{"animal": "c"}都可以通过校验,无需再维护下拉框的label和value映射关系。
内容的提问来源于stack exchange,提问作者codego
相关产品推荐
相关产品推荐

