有没有办法让枚举类型的文本选择字段接受具有人类可读值的传入 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 元素选项以具有不同的标签和值?
您可以覆盖 ChoiceField
的 to_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)'
据我了解(可能不正确),对 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 元素选项以具有不同的标签和值?
您可以覆盖 ChoiceField
的 to_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)'