Есть ли способ заставить текстовое поле выбора типа перечисления принимать входящий почтовый запрос с человекочитаемым значением?
Насколько я понял (возможно, неверно), использование текстовых вариантов типа перечисления для CharFields полезно, поскольку ваша база данных хранит меньше символов в базе данных, но вы все еще можете работать с человекочитаемыми значениями. Однако это кажется контрпродуктивным, когда вы посылаете данные из фронтенда в бэкенд, потому что фронтенд должен посылать значение, которое будет храниться в базе данных, а не читаемое человеком. Например:
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)
Если я отправлю {animal: 'Coyote'} в конечную точку, она скажет "animal is not a valid choice". Вместо этого я должен отправить {animal: 'c'}. Есть ли способ заставить MyModelSerializer принимать человекочитаемые значения вместо того, чтобы настраивать опции элементов выбора на фронтенде, чтобы они имели различные метки и значения?
Вы можете переопределить метод to_internal_value
из ChoiceField
.
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
Почему поля выбора полезны
Насколько я понял (возможно, неверно), использование текстовых вариантов типа перечисления для CharFields полезно, поскольку ваша база данных хранит меньше символов в базе данных
.
Обычно это не является основной мотивацией для использования выбора.
Скорее, из https://docs.djangoproject.com/en/3.2/ref/models/fields/#choices:
Если заданы варианты выбора, они будут принудительно проверяться моделью, и виджетом формы по умолчанию будет поле выбора с этими вариантами выбора вместо стандартного текстового поля.
Для каждого поля модели, для которого установлены варианты выбора, Django добавит метод для получения человекочитаемого имени для текущего значения поля.
label
может быть лениво переводимой строкой.
Пример
Возможно, в базе данных есть название вида:
SPLENDID_POISON_FROG = 'Oophaga speciosa', 'Splendid poison frog'
После того, как этот вид был переклассифицирован как вымерший в 2020 году, вы могли бы захотеть изменить читаемое человеком название, чтобы указать на этот статус без необходимости изменять значения базы данных:
SPLENDID_POISON_FROG = 'Oophaga speciosa', 'Splendid poison frog (Extinct)'