I have a few fields in my user model that are choice fields and am trying to figure out how to best implement that into Django Rest Framework.
Below is some simplifi
I prefer the answer by @nicolaspanel to keep the field writeable. If you use this definition instead of his ChoiceField, you take advantage of any/all of the infrastructure in the built-in ChoiceField while mapping the choices from str => int:
class MappedChoiceField(serializers.ChoiceField):
@serializers.ChoiceField.choices.setter
def choices(self, choices):
self.grouped_choices = fields.to_choices_dict(choices)
self._choices = fields.flatten_choices_dict(self.grouped_choices)
# in py2 use `iteritems` or `six.iteritems`
self.choice_strings_to_values = {v: k for k, v in self._choices.items()}
The @property override is "ugly" but my goal is always to change as little of the core as possible (to maximize forward compatibility).
P.S. if you want to allow_blank, there's a bug in DRF. The simplest workaround is to add the following to MappedChoiceField:
def validate_empty_values(self, data):
if data == '':
if self.allow_blank:
return (True, None)
# for py2 make the super() explicit
return super().validate_empty_values(data)
P.P.S. If you have a bunch of choice fields that all need to be mapped this, way take advantage of the feature noted by @lechup and add the following to your ModelSerializer (not its Meta):
serializer_choice_field = MappedChoiceField