首页 > 解决方案 > 将 Django 序列化程序包装在另一个序列化程序中

问题描述

我需要 django 中的嵌套序列化程序。我有以下可用的序列化程序:

class LocationSerializer(serializers.ModelSerializer):
    coordinate = serializers.SerializerMethodField()
    message = serializers.SerializerMethodField()

    def get_message(self, instance: models.Location):
        if len(instance.message) > 1:
            return instance.message
        return None

    def get_coordinate(self, instance: models.Location):
        if instance.point:
            return {"latitude": instance.point.y, "longitude": instance.point.x}

    class Meta:
        model = models.Location
        fields = ('id', 'street', 'zip', 'phone', 'coordinate', 'message')

这个序列化程序生成的 json 需要像这样包装在一个 json 对象中:

{
    "locations": //here comes the serialized data
}

我用另一个在字段中具有上述序列化程序的序列化程序尝试了以下方式:

class LocationResponseSerializer(serializers.Serializer):

    locations = LocationSerializer(many=True)

但是当我尝试使用这个序列化程序时,我总是会收到以下错误:

 The serializer field might be named incorrectly and not match any attribute or key on the `Location` instance.
 Original exception text was: 'Location' object has no attribute 'locations'.

我究竟做错了什么?仅将其包装在响应对象中是可行的,但这不是解决方案,因为与 Django 一起使用的 swagger 框架似乎不支持这一点。

谢谢您的帮助!

编辑:这是我的观点的列表方法:

def list(self, request, *args, **kwargs):
    # update_compartments()
    queryset = Location.objects.filter(hidden=False).all()
    serializer = LocationResponseSerializer(queryset, many=True)
    return Response(serializer.data)

标签: pythondjangodjango-modelsdjango-rest-framework

解决方案


问题是这个序列化器从 Location.objects.filter(hidden=False).all()查询集中接收数据,所以它一个一个地序列化这些数据。

class LocationResponseSerializer(serializers.Serializer):
    locations = LocationSerializer(many=True)

如果包装响应对您不起作用,您可以尝试

class LocationResponseSerializer(serializers.Serializer):
    locations = LocationSerializer(source="*")

但这也不是你想要的,因为它会locations为每条记录生成queryset

另一种选择是你的看法

def get_queryset(self):
    locations = Location.objects.filter(hidden=False).all()
    return { 'locations': locations }

或将您的列表方法更改为 smt like

def list(self, request, *args, **kwargs):
    # update_compartments()
    data = Location.objects.filter(hidden=False).all()
    queryset = { 'locations': data }
    serializer = LocationResponseSerializer(queryset)
    return Response(serializer.data)

但是在这种情况下,您可能还需要编写一个自定义分页器,因为如果您需要它,它不会开箱即用

希望有帮助


推荐阅读