使用SlugRelatedField进行嵌套序列化

时间:2014-08-04 17:33:02

标签: django serialization django-models django-rest-framework api-design

我有一个模型结构:

class Student(models.Model):
    created = models.DateTimeField(editable=False)
    # should modifieid be editable?
    modified = models.DateTimeField(editable=False)
    english_name = models.CharField(max_length=SHORT_LENGTH)
    # TODO: make sure chinese characters work!
    chinese_name = models.CharField(max_length=SHORT_LENGTH)
    # student_id = ####

    def save(self, *args, **kwargs):
        # store curr time ahead so we don't account for processor cycles
        curr_time = timezone.now()

        # if we don't have an ID, we're brand new!
        if not self.id:
            self.created = curr_time
        self.modified = curr_time
        return super(Student, self).save(*args, **kwargs)

class SeminarMembership(models.Model):
    student = models.ForeignKey('Student')
    seminar = models.ForeignKey('Seminar', related_name = "memberships")

class Seminar(models.Model):
    created = models.DateTimeField(editable=False)
    modified = models.DateTimeField()
    #userID = ############
    title = models.CharField(max_length=LONG_LENGTH)
    #description

    def save(self, *args, **kwargs):
        # store curr time ahead so we don't account for processor cycles
        curr_time = timezone.now()

        # if we don't have an ID, we're brand new!
        if not self.id:
            self.created = curr_time
        self.modified = curr_time
        return super(Seminar, self).save(*args, **kwargs)

SeminarMembership是建立学生 - 研讨会配对的枢纽。

我正在尝试让DRF序列化一个单独的研讨会实体,以便JSON响应包括通过支点在该研讨会中注册的所有学生。为此,我检索与某个研讨会相关的所有成员资格(很多= True):

class SeminarSerializer(serializers.ModelSerializer):
    memberships = SeminarMembershipSerializer(many=True)
    class Meta:
        model = Seminar
        read_only_fields = ('title',)

然后,由于SeminarMembership的Serializer如下:

class SeminarMembershipSerializer(serializers.ModelSerializer):
    # needs to be read_only?
    student = StudentSerializer(many=False)
    seminar = serializers.PrimaryKeyRelatedField(many=False, read_only=True)

    class Meta:
        model = SeminarMembership

当我将SeminarSerializer修改为以下内容时,我收到“Student object not serializable”错误:

   class SeminarSerializer(serializers.ModelSerializer):
        memberships = serializers.SlugRelatedField(many=True, read_only=True, slug_field='student')
        class Meta:
            model = Seminar
            read_only_fields = ('title',)

理论上,DRF应该认识到应该使用StudentSerializer从SeminarMembershipSerializer的实现序列化SlugRelatedField,然后继续序列化外部学生对象字段以用于JSON响应。但后来我遇到了一个“学生对象”而不是JSON可序列化。

1 个答案:

答案 0 :(得分:2)

首先,如果您在SeminarMembership中拥有的唯一字段是学生和研讨会,那么简单的ManyToMany字段就足够了。如果没有,您应该使用字段来实现此关系(here are the docs

然后,您必须声明 SeminarSerializer AND StudentSerializer (您不需要会员序列化程序)。

  

我正在尝试让DRF序列化一个单独的研讨会实体,以便JSON响应包括通过支点在该研讨会中注册的所有学生。

为此,您必须将您的学生安排在SeminarSerializer中:

class SeminarSerializer(serializers.ModelSerializer):
    students = StudentSerializer(many=True)
    class Meta:
        model = Seminar
        read_only_fields = ('students',)

此外,我强烈建议您使用django-extensions - > TimeStampedModel而不是添加您自己创建和修改的字段。它非常易于使用,它可以为您完成所有工作(因此您不必再覆盖保存功能)。