I\'m implementing some REST API in DRF with ModelViewSet and ModelSerializer. All my APIs use the JSON format and some of my models use ChoiceField
There's no way other than overriding your serializer. Please take a look here, to see how it can be done.
I found a possible solution, namely defining my own field as follow:
class MyChoiceField(serializers.ChoiceField):
def to_representation(self, data):
if data not in self.choices.keys():
self.fail('invalid_choice', input=data)
else:
return self.choices[data]
def to_internal_value(self, data):
for key, value in self.choices.items():
if value == data:
return key
self.fail('invalid_choice', input=data)
It works the same way as to ChoiceField, but returns and accepts labels instead of keys.
previous answers helped me a lot but not worked for me as I use Django version 3 and DRF version 3.11 , so I came up with this:
# models.py
class Ball(models.Model):
class Types(models.TextChoice):
VOLLYBALL = 'VB', gettext_lazy('VollyBall')
FOOTBALL = 'FB', gettext_lazy('FootBall')
type = models.CharField(max_length=2, choices=Types.choices)
# serializers.py
class CustomChoiceField(serializers.ChoiceField):
def to_representation(self, value):
if value in ('', None):
return value
choice_dict = {str(key): key.label for key in self.choices}
return choice_dict.get(str(value), value)
def to_internal_value(self, data):
if data == '' and self.allow_blank:
return ''
try:
choice_dict = {key.label: str(key) for key in self.choices}
return choice_dict[str(data)]
except KeyError:
self.fail('invalid_choice', input=data)
class BallSerializer(serializers.ModelSerializer):
type = CustomChoiceField(choices=Book.Types)
class Meta:
model = Book
fields = ['type']