DRF ListSerializer错误:期望一个项目列表,但得到类型" int"

时间:2015-11-27 19:29:56

标签: python serialization django-rest-framework django-serializer

我试图通过将<video id="really-cool-video" class="video-js vjs-default-skin" controls preload="auto" width="640" height="264" poster="really-cool-video-poster.jpg" data-setup='{ "autoplay": true, "preload": "auto"}'> 传递给序列化程序来序列化对象列表。如果我传递实例而不是没有many=True的列表,则序列化程序可以正常工作。我仍然试图了解序列化程序如何工作,但无法调试此问题。我正在使用DRF 3.3.0

查看下面第3行的错误

many=True

串行器:

class BubbleExamView(object):
    def get_context_data(self, **kwargs):
       sections = self.data.exam.section_set.all()
       if serializers.TakeSectionSerializer(
           sections, self.data.user.id, many=True).is_valid(raise_exception=True):
              sections_json = renderer.render(serializers.TakeSectionSerializer(
            sections, self.data.user.id, many=True).data)
            context = {
                'exam': self.data.exam,
                'sections_json': sections_json,
                'student': self.data.user,
                'course': self.data.exam.course,
            }
            context.update(kwargs)
       return super(BubbleExamView, self).get_context_data(**context)
       ....
       ....

回溯

class FullAssetSerializer(serializers.ModelSerializer):
    image = serializers.SerializerMethodField('get_image_url')

    def get_image_url(self, asset):
        if asset.image:
            return default_storage.url(asset.image.name)

    class Meta:
        model = models.Asset
        fields = ('id', 'asset_type', 'text', 'image',)

class FullQuestionAssetSerializer(serializers.ModelSerializer):
    asset = FullAssetSerializer()

    class Meta:
        model = models.QuestionAsset
        fields = ('id', 'order', 'asset')

class StubbedSectionSerializer(serializers.ModelSerializer):
    """Serialize a section object, without any of the assets or questions"""
    class Meta:
        model = models.Section
        fields = ('id', 'exam', 'name', 'number', 'duration', 'break_duration')

class TakeSectionSerializer(StubbedSectionSerializer):
    """Serialize a section object, along with all the assets and questions that are contained in the section
    in order to display it to a student taking the exam"""
    class Meta(StubbedSectionSerializer.Meta):
        fields = StubbedSectionSerializer.Meta.fields + ('assets', 'examquestions')

    examquestions = serializers.SerializerMethodField('get_exam_questions')
    assets = FullAssetSerializer(many=True)

    def __init__(self, section, user_id, **kwargs):
        super(TakeSectionSerializer, self).__init__(section, **kwargs)
        self.user_id = user_id

    def get_exam_questions(self, section):
        examquestions = section.examquestion_set.all()

        kwargs = {
            'exam_question__section_id':section.id,
            'exam_response__user_id':self.user_id,
        }
        choiceresponses = models.ChoiceQuestionResponse.objects.filter(**kwargs)
        textresponses = models.TextQuestionResponse.objects.filter(**kwargs)

        for eq, response in utils.zip_responses(
            examquestions,
            itertools.chain(choiceresponses, textresponses),
            'exam_question_id'
        ):
            eq.response = response

        return ExamQuestionSerializer(examquestions, many=True).data

2 个答案:

答案 0 :(得分:2)

您只是将用户ID作为数据传递给序列化程序,并且序列化程序正在抱怨,因为这绝对不是正确的数据格式。

if serializers.TakeSectionSerializer(
       sections, self.data.user.id, many=True).is_valid(raise_exception=True):

序列化程序需要一个完整的数据字典(键是序列化程序字段),如果指定many=True,它们需要一个字典列表。您只传递单个值,即用户的ID,而不是字典列表。因此,DRF抱怨只给出一个整数而不是一个项目列表。

我建议looking at the DRF tutorial更好地了解序列化的工作原理。

答案 1 :(得分:0)

我不会因此而受到赞扬,但这是有效的答案,并由DRF人员解决他们的github问题。

我检查了DRF中的Serializer代码,我们覆盖了__new__,这意味着你的__init__构造函数覆盖是无用的(之前发生了魔法)。这就是代码行在DRF来源中 我建议你删除TakeSectionSerializer中的__init__。相反,您应该在上下文TakeSectionSerializer(sections, context={'user_id': self.user.id}, many=True)中传递self.user.id并相应地修改TakeSectionSerializer代码。

如果您不知道如何获取上下文以便在get_exam_questions中使用它,您可能需要查看我们的“包含额外上下文”示例。基本上self.context['user_id']应该有效。 这肯定会解决你的问题。