有没有办法让枚举类型的文本选择字段接受具有人类可读值的传入 post 请求?

Is there a way to get an enumeration type text choice field to accept an incoming post request with the human readable value?

据我了解(可能不正确),对 CharFields 使用枚举类型文本选择很有用,因为您的数据库在数据库中存储的字符较少,但您仍然可以使用人类可读的值。但是,当您 post 将数据从前端传输到后端时,这似乎适得其反,因为前端必须 post 将存储在数据库中的值,而不是人类可读的值。例如:

class MyModel(models.Model):
    class Animals(models.TextChoices):
        ALLIGATOR = 'a', 'Alligator'
        BEAR = 'b', 'Bear'
        COYOTE = 'c', 'Coyote'

    animal = models.CharField(max_length=20, choices=Animals.choices)

如果我post {animal: 'Coyote'}到终点,它会说'animal is not a valid choice'。我必须 post {animal: 'c'} 来代替。有没有一种方法可以让 MyModelSerializer 接受人类可读的值,而不必设置前端 select 元素选项以具有不同的标签和值?

您可以覆盖 ChoiceFieldto_internal_value 方法。

from rest_framework.fields import ChoiceField


class AllowHumanReadableNameAsValueChoiceField(ChoiceField):

    def to_internal_value(self, data):
        value = next((v for k, v in self.choices.items()), None)
        if value is not None:
            return value
        return super().to_internal_value(data)

用法:

class MyModelSerializer(ModelSerializer):
    class Meta:
        model = MyModel
        fields = '__all__'

    serializer_choice_field = AllowHumanReadableNameAsValueChoiceField

为什么选择字段很有用

It was my understanding (maybe incorrect) that using enumeration type text choices for CharFields is useful because your database stores less characters on the database

这通常不是使用选项的主要动机。

而是来自https://docs.djangoproject.com/en/3.2/ref/models/fields/#choices

If choices are given, they’re enforced by model validation and the default form widget will be a select box with these choices instead of the standard text field.

For each model field that has choices set, Django will add a method to retrieve the human-readable name for the field’s current value.

The label can be a lazy translatable string.

一个例子

您可能在数据库中有物种名称:

SPLENDID_POISON_FROG = 'Oophaga speciosa', 'Splendid poison frog'

此物种在 2020 年被重新归类为灭绝后,您可能希望更改人类可读的名称以指示该状态,而无需更改数据库值:

SPLENDID_POISON_FROG = 'Oophaga speciosa', 'Splendid poison frog (Extinct)'