2015-03-25 1 views
1

Я использую Django 1.7.7 и Django Rest Framework 3.1.1.Ключевая ошибка в Django Rest Framework при использовании serializers.ChoiceField с кортежами

Когда я сериализации эту модель

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) 

с помощью этого Viewset/сериалайзер:

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() 

Я получаю KeyError '10' (или любой другой QUESTION_TYPES ключ является первым сериализовать из вопросов Таблица).

ошибка, кажется, брошенные rest_framework/fields.py в to_representation возвратных self.choice_strings_to_values ​​[six.text_type (значение)]

есть все, что очевидно, что я делаю неправильно? Есть ли проблема с использованием кортежей с serializer.ChoiceField?

Джон

+0

Что о: 'ChoiceField (выбор = Вопрос. QUESTION_TYPES) ​​'? – mariodev

+0

Это имеет желаемый эффект, чтобы не выдавать ошибку, но она по-прежнему отображает ключ, а не текст, такой как «рекламный ролик». Я также попробовал 'type = serializers.CharField (source = 'get_type_display')', и пока он отображает текст правильно, а не ключ, он выглядит только для чтения. Я не могу, чтобы жизнь меня писала, даже если я пытаюсь написать ключ. – John

ответ

2

Похож ChoiceField имеет некоторые проблемы при попытке переопределить поведение в самом сериализаторе.

Вы можете обойти это, хотя при использовании двух отдельных полей:

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 
2

Это все сводится к этому line в классе ChoiceField. Он использует ключ дважды.

self.choice_strings_to_values = dict([ 
    (six.text_type(key), key) for key in self.choices.keys() 
]) 

Вы можете изменить это поведение, создавая собственное поле сериалайзер расширив класс ChoiceField

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() 
     ]) 
+0

Ваш класс отлично работает и так же, как я думал, что ChoiceField будет работать. Вы знаете, если об этом сообщается об ошибке? Кажется, что такая очевидная ошибка, что мне что-то не хватает. Благодарю. –

+0

На самом деле, после использования этого класса некоторое время мы вернулись к обычной реализации, потому что это упростило наш конец javascript. Поэтому я не думаю, что это ошибка, просто другой вариант использования. – Felipe

+0

Спасибо, это решение работает для меня. Это код для Python 3 http://stackoverflow.com/a/35575125/727716 – moisesgallego

1

Эквивалентная на Python 3

self.choice_strings_to_values = dict([ 
    (six.text_type(key), str(value)) for key, value in self.choices.items() 
]) 
Смежные вопросы