返回由主键索引的dict

时间:2017-12-28 21:25:39

标签: django django-rest-framework

我有一个简单的API端点,它返回MyModel的列表。

views.py:

@api_view(['GET'])
def index(request):
    myModel = MyModel.objects.all()
    serializer = MyModelSerializer(myModel, many=True)
    return Response(serializer.data)

serializers.py

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ['field1', 'field2']

现在我想返回一个由主键索引的模型的序列化字典(这是一个CharField)。

{
    'pk1':{
           'field1': 'fo',
           'field2': 'bar',
     },
    'pk2':{
           'field1': 'fobar',
           'field2': 'foo',
     }
}

[编辑]根据要求,这是模型:

from django.db import models


class MyModel(models.Model):
    id = models.CharField(primary_key=True)
    field1 = models.FloatField(null=True)
    field2 = models.FloatField(null=True)

4 个答案:

答案 0 :(得分:0)

您可以遍历查询集。在index视图中:

@api_view(['GET'])
def index(request)
    data = dict()
    for element in MyModel.objects.all():
        dict[element.id] = {'field1': element.field1, 'field2': element.field2}
    return Response(data)

答案 1 :(得分:0)

您可以在序列化程序中覆盖to_representation方法

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ['field1', 'field2']

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        return {instance.pk: ret}

答案 2 :(得分:0)

您需要创建一个返回字典的自定义ListSerializer。

from django.db import models
from rest_framework import serializers

class DictSerializer(serializers.ListSerializer):
    def to_representation(self, data):
        iterable = data.all() if isinstance(data, models.Manager) else data
        return [
            (item.id, self.child.to_representation(item)) for item in iterable
        ]

    @property
    def data(self):
        ret = super(DictSerializer, self).data
        return serializers.ReturnDict(ret, serializer=self)

然后,当many = True时,您必须指定ModelSerializer应使用此自定义。您可以通过在ModelSerializer的Meta中设置list_serializer_class来完成此操作。

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ['field1', 'field2']
        list_serializer_class = DictSerializer

答案 3 :(得分:0)

如果您想提高效率,可以遵循他的Gabriel Muj解决方案,但不会提供您想要的即用型解决方案。他的解决方案将提供如下输出:

[{
    'pk1': {
      'field1': 'fo',
      'field2': 'bar',
    }
  },
  {
    'pk2': {
      'field1': 'fobar',
      'field2': 'foo',
    }
  }
]

首先根据他的解决方案更改序列化器:

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ['field1', 'field2']

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        return {instance.pk: ret}

但是要获得您所要的内容,您需要使用集合中的ChainMap。现在,您需要像这样更改视图:

from collections import ChainMap

@api_view(['GET'])
def index(request):
    myModel = MyModel.objects.all()
    serializer = MyModelSerializer(myModel, many=True)
    data_dict = dict(ChainMap(*serializer.data))

    return Response(data_dict)

对于此代码段,您需要确保其python 3.3+。这将提供良好的性能。在优化我的代码时,我发现这种解决方案不太繁琐。