在一对一关系模型的序列化器中添加额外字段

时间:2019-06-22 05:40:37

标签: python django django-rest-framework

在这个项目中,我有两个模型Student和Parent通过一对一字段相互关联。

在“父级序列化程序”中,我想添加“学生”属性,例如“年龄”。我正在考虑在两种情况下都使用SerializerMethodField是他们的更好方法吗?

我没有得到有关如何获取对象属性的查询,很少有解释会很好。

这是我到目前为止所做的。

Models.py

class Student(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, default=None)
    batch = models.ForeignKey(Batch, on_delete=models.CASCADE, null=True, related_name='students')
    email = models.EmailField(null=True)
    phone_number = models.CharField(max_length=10, null=True)
    dob = models.DateField(blank=True, null=True, help_text="Enter in the following format : YYYY-MM-DD")
    address = models.TextField(max_length=150, null=True)
    age = models.IntegerField(blank=True)
    image = models.ImageField(upload_to='profile_pictures', default='student_image.png', blank=True)

    @property
    def remarks(self):
        return self.remark_set.all()

    @property
    def marks(self):
        return self.marks_set.all()

    def __str__(self):
        return self.user.firstName + ' ' + self.user.lastName

class Parent(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, default=None)
    child = models.ForeignKey(Student, on_delete=models.CASCADE)
    email = models.EmailField(null=True)
    phone_number = models.CharField(max_length=10, null=True)
    address = models.TextField(max_length=150, null=True)
    image = models.ImageField(upload_to='profile_pictures', default='student_image.png', blank=True)

    def __str__(self):
        return self.user.firstName + ' ' + self.user.lastName


Serilaizer.py

class ParentSerializer(serializers.HyperlinkedModelSerializer):
    student_age = serializers.SerializerMethodField()
    student_batch = serializers.SerializerMethodField()
    parent_name = serializers.SerializerMethodField()

    class Meta:
        model = Parent
        fields = "__all__"

    def get_student_age(self, obj):
        return Parent.objects.get(child__age = self.obj.user.child)

    def get_student_batch(self, obj):
        return Parent.objects.get(child__bacth = self.obj.user.child)

    def get_parent_name(self, user):
        return Parent.objects.get(user=self.request.user)


Views.py

class ParentView( mixins.ListModelMixin, mixins.RetrieveModelMixin,viewsets.GenericViewSet):
    queryset = Parent.objects.all()
    serializer_class = serializers.ParentSerializer

1 个答案:

答案 0 :(得分:1)

第一种方式:

from apps.models import Student, parent

class BasicUserSerializer(serializers.ModelSerializer):
    class Meta:
       model =  User
       fields = "__all__"


class BasicStudentSerializer(serializers.ModelSerializer):
    class Meta:
       model =  Student
       fields = "__all__"


class ParentSerializer(serializers.ModelSerializer):
    user = BasicUserSerializer(read_only=True,many=False)
    child = BasicStudentSerializer(read_only=True, many=True)

    class Meta:
        model = Parent
        fields = '__all__'

您可以这样做。它替换了您想要的序列化器字段,并且如果父级有多个子级,则在子级字段中您将拥有所有新子级的信息作为字典。

================================================ =================

第二种方法是使用HyperLinkModel

class ParentSerializer(serializers.ModelSerializer):
    user = serializers.HyperlinkedRelatedField(read_only=True,many=False)
    child = serializers.HyperlinkedRelatedField(read_only=True, many=True)

    class Meta:
        model = Parent
        fields = '__all__'

但是请注意,以第一种方式,您将拥有一个独立的序列化器类,每次您需要序列化与UserChild相关的模型类时,都可以简单地使用它们。