使用嵌套序列化器时避免嵌套对象

时间:2019-10-14 20:56:33

标签: django django-models django-rest-framework

我有两个模型,一个包含在ForeignKey关系中的另一个模型,我想制作一个API,该API将返回这两个模型的组合,因此我尝试使用嵌套的序列化器来添加相关模型,但是数据并非全部处于同一级别,相关模型是第一个内部的对象。

这里是模型

class ModelOne(models.Model):
    last_counter = models.IntegerField()


class ModelTwo(models.Model):
    model_one = models.ForeignKey(ModelOne, on_delete=models.CASCADE)
    category = models.CharField(max_length=64)
    counter_type = models.CharField(max_length=32)

这是序列化器

class ModelOneSerializer(serializers.ModelSerializer):
    class Meta:
        model = ModelOne
        fields = "__all__"


class ModelTwoSerializer(serializers.ModelSerializer):
    model_one= ModelOneSerializer(read_only=True)

    class Meta:
        model = ModelTwo
        fields = "__all__"

这将从API返回,形式为

{
   "category" : ...,
   "counter_type" : ...,
   "model_one" : {
     "last_counter" : ...
   }
}

但是我希望这样的答复,我希望它更像这样

{
   "category" : ...,
   "counter_type" : ...,
   "last_counter" : ...,
}

有没有一种方法可以通过序列化器来实现?

2 个答案:

答案 0 :(得分:1)

使用SerializerMethodField

from rest_framework.fields import SerializerMethodField

class ModelTwoSerializer(serializers.ModelSerializer):
    last_counter = SerializerMethodField()

    class Meta:
        model = ModelTwo
        fields = "__all__"

    def get_last_counter(self, obj):
        return ModelOneSerializer(obj.model_one).data['last_counter']

使用field_one创建自定义字段(例如SerializerMethodField)时,必须创建一个名为get_field_one的方法,该方法才能被序列化程序自动检测。

答案 1 :(得分:1)

您可以使用drf字段中的SerializerMethodField来完成您想做的事情:

SerializerMethodField是一个只读字段,可通过在其附加到的序列化程序类上调用一个方法来在请求处理时计算其值。例如,对于您的情况,它将如下所示。请注意,已计算的last_counter已添加到序列化模型字段中。

from rest_framework.fields import SerializerMethodField

class ModelTwoSerializer(serializers.ModelSerializer):
    last_counter = serializers.SerializerMethodField()

class Meta:
    model = ModelTwo
    fields = ["category", "counter_type", "last_counter"]

def get_last_counter(self, obj):
    return int(obj.model_one.last_counter)

SerializerMethodField接受method_name,但是使用默认模式命名这些方法通常更方便,即get_。只需确保您不会用任何繁重的操作来负担方法字段的负担。

您可以阅读有关官方文档的更多信息:enter link description here