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']