Reputation: 6065
I am using Django 1.7.7 and Django Rest Framework 3.1.1.
When I serialize this model
class Question(models.Model):
QUESTION_TYPES = (
(10,'Blurb'),
(20,'Group Header'),
(21,'Group Footer'),
(30,'Sub-Group Header'),
(31,'Sub-Group Footer'),
(50,'Save Button'),
(100,'Standard Question'),
(105,'Text-Area Question'),
(110,'Multiple-Choice Question'),
(120,'Standard Sub-Question'),
(130,'Multiple-Choice Sub-Question')
)
type = models.IntegerField(default=100,choices=QUESTION_TYPES)
using this viewset/serializer:
class QuestionSerializer(serializers.ModelSerializer):
type = serializers.ChoiceField(choices='QUESTION_TYPES')
class Meta:
model = Question
class QuestionViewSet(viewsets.ModelViewSet):
model = Question
serializer_class = QuestionSerializer
def get_queryset(self):
return Question.objects.all()
I get a KeyError '10' (or whatever QUESTION_TYPES key is the first to be serialized from the Questions table).
The error seems to be thrown by rest_framework/fields.py in to_representation return self.choice_strings_to_values[six.text_type(value)]
Is there anything obvious I am doing wrong? Is there a problem using tuples with serializer.ChoiceField?
John
Upvotes: 1
Views: 3492
Reputation: 421
The equivalent on Python 3
self.choice_strings_to_values = dict([
(six.text_type(key), str(value)) for key, value in self.choices.items()
])
Upvotes: 1
Reputation: 440
It all comes down to this line in the ChoiceField class. It uses the key twice.
self.choice_strings_to_values = dict([
(six.text_type(key), key) for key in self.choices.keys()
])
You can change this behavior by creating your own field serializer extending the ChoiceField class
class DisplayChoiceFieldSerializers(serializers.ChoiceField):
def __init__(self, *args, **kwargs):
super(DisplayChoiceFieldSerializers, self).__init__(*args, **kwargs)
self.choice_strings_to_values = dict([
(six.text_type(key), unicode(value)) for key, value in self.choices.iteritems()
])
Upvotes: 2
Reputation: 15519
Seems like ChoiceField
has some problems when trying to override the behavior in the serializer itself.
You can go around this though by using two separate fields:
class QuestionSerializer(serializers.ModelSerializer):
type = serializers.ChoiceField(choices=Question.QUESTION_TYPES)
type_display = serializers.CharField(source='get_type_display',
read_only=True)
class Meta:
model = Question
Upvotes: 2