Django API在JSON响应中嵌套了多对多字段

时间:2018-01-26 09:15:34

标签: python json django rest api

我正在尝试使用Django休息框架创建一个API,但我正在努力修改我想要的JSON响应。如果您还有其他需要,请询问,谢谢您的帮助!

models.py:

class Feature(models.Model):
    name = models.CharField(max_length=255, unique=True, null=True)

    def __str__(self):
        return "{}" .format(self.name)

    def save(self, *args, **kwargs):
        super(Feature, self).save(*args, **kwargs)

class Opponent(models.Model):
    name = models.CharField(max_length=255, unique=True, null=True)
    features = models.ManyToManyField(Feature, blank=True, null=True)

    def __str__(self):
        return "{}" .format(self.name)

    def save(self, *args, **kwargs):
        super(Opponent, self).save(*args, **kwargs)

serializers.py:

class FeatureSerializer(serializers.ModelSerializer):
    opponents = serializers.RelatedField(many=True)

    class Meta:
        model = Feature

views.py:

@csrf_exempt
@jsonify
def get_opponents(request):
    if request.method == 'OPTIONS':
        return HttpResponse()

opponents = list(Opponent.objects.all().values('id', 'features'))
return opponents

def jsonify(f):
    @wraps(f)
    def wrapper(*args, **kwds):
        response = f(*args, **kwds)
        if isinstance(response, HttpResponse):
            return response
        return HttpResponse(simplejson.dumps(response, ignore_nan=True))

    return wrapper

JSON回复:

[
    {
        "id": 1,
        "features__name": "feature1"
    },
    {
        "id": 1,
        "features__name": "feature2"
    }
]

我想要的是什么:

[
    {
        "id": 1,
        "features": ["feature1", "feature2"]
    }
]

1 个答案:

答案 0 :(得分:1)

正如我在评论中所说,你根本就没有使用Django REST框架 - 通过使用标准视图和你的jsonify装饰器,你绕过了DRF为你做的一切,包括序列化器。

首先,您应该停止这样做,而是使用正确的DRF视图。这使您能够创建自定义序列化程序,为您提供所需的结构。

由于实际上是Opponents及其相关功能,您想要序列化,因此您应该创建一个OpponentSerializer。您的功能模型已经定义了一个返回名称的__str__方法,因此您可以在序列化程序中使用StringRelatedField自动执行此操作。

现在您只需要一个使用序列化程序的视图。这里最简单的方法是使用ListAPIView,它可以自动完成项目列表所需的一切。所以:

class OpponentSerializer(serializers.ModelSerializer):
    features = serializers.StringRelatedField(many=True, read_only=True)

    class Meta:
        model = Opponent
        fields = ('id', 'features')

class OpponentList(generics.ListAPIView):
    queryset = Opponent.objects.all()
    serializer_class = OpponentSerializer