Django Rest Framework JSON序列化器

6
我希望从Django rest framework获得json响应,因此我有以下Json响应: .
[
    {
        "id": 1,
        "TitleEnglish": "Tiny Talents Program",
        "TitleArabic": "Tiny Talents Program",
        "DescriptionEnglish": "Timing: 8:00 am till 1:00 pm",
        "DescriptionArabic": "Timing: 8:00 am till 1:00 pm",
        "CategoryEnglish": "Art & Education ",
        "CategoryArabic": "Art & Education ",
        "Date": "2015-05-07",
        "Status": true,
        "Image": "--"
    }
]

但是我需要这样的响应:
{
"data": [
    {
        "id": 1,
        "TitleEnglish": "Tiny Talents Program",
        "TitleArabic": "Tiny Talents Program",
        "DescriptionEnglish": "Timing: 8:00 am till 1:00 pm",
        "DescriptionArabic": "Timing: 8:00 am till 1:00 pm",
        "CategoryEnglish": "Art & Education ",
        "CategoryArabic": "Art & Education ",
        "Date": "2015-05-07",
        "Status": true,
        "Image": "--"
    }
       ]
}

我的序列化代码如下:

class PromotionSerializer(serializers.HyperlinkedModelSerializer):
    CategoryEnglish  = serializers.CharField(read_only=True, source="Category.TitleEnglish")
    CategoryArabic  = serializers.CharField(read_only=True, source="Category.TitleArabic")
    class Meta:
        model = Promotion
        fields = ('id', 'TitleEnglish', 'TitleArabic', 'DescriptionEnglish', 'DescriptionArabic', 'CategoryEnglish','CategoryArabic', 'Date','Status','Image')

你需要创建一个自定义渲染器。http://www.django-rest-framework.org/api-guide/renderers/#custom-renderers 我从未尝试过这个方法,但我认为它适合你的问题。 - Edwin Lunando
3个回答

7

我通过更改我的视图解决了我的问题:

我添加了一个列表方法,解决了我的问题:

def list(self, request):
    queryset = Promotion.objects.all()
    serializer_class = PromotionSerializer(queryset, many=True)
    serialized_data =  {'data': serializer_class.data}
    return Response(serialized_data)

太好了!我也在做同样的事情,并通过在序列化器中的Meta类中定义list_serializer_class来完成。我会更新我的先前答案。 - Rahul Gupta
这是另一种选项,可以用更少的代码和更少的覆盖来解决问题!+1 - Rahul Gupta

2
最简单的解决方案是重写to_representation方法。
def to_representation(self, instance):
    data = super(PromotionSerializer, self).to_representation(instance)
    return {'data': data }

这很优雅! - NFern

2
我认为你可以通过自定义ListSerializer的行为来实现这一点,该行为用于创建list请求的序列化响应。
我们可以创建一个名为PromotionListSerializer的自定义序列化器,当多个实例传递给序列化器进行序列化时,使用many=True参数。
在我们的PromotionListSerializer类中覆盖data属性,以返回我们的自定义表示形式。
class PromotionListSerializer(serializers.ListSerializer):

    @property
    def data(self):
        # call the super() to get the default serialized data
        serialized_data =  super(PromotionListSerializer, self).data       
        custom_representation = {'data': serialized_data} # insert the above response in a dictionary
        return custom_representation

然后在您的PromotionSerializer中,在Meta中指定此自定义列表序列化类。当序列化多个实例时,将使用此自定义列表序列化类。

class PromotionSerializer(serializers.HyperlinkedModelSerializer):
    CategoryEnglish  = serializers.CharField(read_only=True, source="Category.TitleEnglish")
    CategoryArabic  = serializers.CharField(read_only=True, source="Category.TitleArabic")
    class Meta:
        model = Promotion
        fields = ('id', 'TitleEnglish', 'TitleArabic', 'DescriptionEnglish', 'DescriptionArabic', 'CategoryEnglish','CategoryArabic', 'Date','Status','Image')

        # define the custome list serializer class to be used
        list_serializer_class = PromotionListSerializer

解决方案2:

覆盖视图的list方法并返回自定义表示,而不是默认响应,就像您在您的答案中所述的那样。

扩展原作者的答案,这将支持分页响应。以下是DRF中的实际代码,我只是在最后返回了custom_representation而不是serializer.data

def list(self, request, *args, **kwargs):
    instance = self.filter_queryset(self.get_queryset())
    page = self.paginate_queryset(instance)
    if page is not None:
        serializer = self.get_pagination_serializer(page)
    else:
        serializer = self.get_serializer(instance, many=True)
    serialized_data = serializer.data
    custom_representation = {'data': serialized_data}
    return Response(custom_representation)

仍然有问题[ { "data": { "id": 1, "TitleEnglish": "Tiny Talents Program", "TitleArabic": "Tiny Talents Program", "DescriptionEnglish": "Timing: 8:00 am till 1:00 pm", "DescriptionArabic": "Timing: 8:00 am till 1:00 pm", "CategoryEnglish": "Art & Education ", "CategoryArabic": "Art & Education ", "Date": "2015-05-07", "Status": true, "Image": "--" } } ] - Muhammad Naeem Paracha
我想删除起始数组,然后从字典开始,接着是数据数组,详见我的问题格式。谢谢你的帮助 :) - Muhammad Naeem Paracha
更新了答案。实际上,仅覆盖to_representationlist请求的情况下不起作用,即在序列化多个实例时。 DRF在调用to_represention后在.data属性中使用ReturnList类,这又给了我一个列表。我可以通过创建自定义列表序列化器类并覆盖data属性来解决问题,以便返回我的自定义表示。 - Rahul Gupta
你在回答中提供的方法也可以正确地解决这个问题。我稍微扩展了你的解决方案,请检查一下。 :) - Rahul Gupta
谢谢,这也会解决我的问题,但我已经解决了 :) - Muhammad Naeem Paracha
很好!如果这对你有用的话,别忘了接受你的答案,因为它可能会帮助其他遇到同样问题的人。 :) - Rahul Gupta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接