[Fixed]-Django Rest Framework to return dicts instead of OrderedDicts

25👍

class/models are serialized into an OrderedDict type to be consumed by the Response method through this import from rest_framework.response import Response in combination with Django Rest Framework Views. It will typically return the data in a content-type that is either assigned at runtime through the DEFAULT_RENDERER_CLASSES project setting, assigned through a serializer property that is passed on initialization, or will be determined by the Accept header sent during the request. Details can be found in the DRF documentation at http://www.django-rest-framework.org/api-guide/renderers/.

Thus, calling Response(BentoSerializer(obj).data) should return JSON formatted data to the client when passed through a view such as APIView, or a route on a ModelViewSet.

However, you can also just import json and call json.dumps(BentoSerializer(obj).data) and the desired JSON will be output. I tested this with my own serializers in the django shell.

EDIT

Note that you cannot simply dump a datetime… You will likely end up having to write a patch to convert datetime and date objects to the format you expect.

eg.

def json_dt_patch(o):
    import datetime
    from decimal import Decimal

    if isinstance(o, datetime.date) or isinstance(o, datetime.datetime):
        return o.strftime("%Y/%m/%d %H:%M:%S")
    elif isinstance(o, Decimal):
        return str(o)
    return o

import json

json.dumps(data, default=json_dt_patch)

2👍

While getting Ordered Dict from serializer validator you can convert it easily to the full form of Dict like JSONRenderer. This is usually returned in nested serializers.

    serializer = XXXSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    payload = loads(dumps(serializer.data))
    print(payload)

From

{'connection_alias': 'dev', 'payment_gateway_type': 'Stripe', 'restaurant_id': 'STRIPE_SANDBOX_TEST', 'card_info': OrderedDict([('card_type', 'VISA'), ('card_number', 'xxxxx'), ('card_expiry_month', 'xx'), ('card_expiry_year', 'xx'), ('card_cvc', 'xxx'), ('cardholder_name', 'xxxxxx')])

To

{'connection_alias': 'dev', 'payment_gateway_type': 'Stripe', 'restaurant_id': 'STRIPE_SANDBOX_TEST', 'card_info': {'card_type': 'VISA', 'card_number': 'xxxxxxxxx', 'card_expiry_month': 'xx', 'card_expiry_year': 'xx', 'card_cvc': 'xxx', 'cardholder_name': 'xxxxxx'}}

1👍

This is addendum to @NicholasClaudeLeBlanc’s answer.

I couldn’t get json.dumps to work in my context. The actual JSON renderer used by django-rest-framework can be obtained like this:

from rest_framework.renderers import JSONRenderer
renderer = JSONRenderer()
renderer.render

renderer’s documentation

0👍

you can use:

class BentoSerializer(ModelSerializer):
    zones = SerializerMethodField()
    lead_zone = SerializerMethodField()

    def get_zones(self, obj):
        zone_data = ZoneSerializer(obj.zones, many=True)
        data_list = []
        for i in zone_data.data:
            data_list.append(dict(i))
        return data_list

    def get_lead_zone(self, obj):

        lead_zone_data = ZoneSerializer(obj.lead_zone, many=True)
        data_list = []
        for i in lead_zone_data.data:
            data_list.append(dict(i))
        return data_list

    class Meta:
        model = Bento
        fields = ('lead_zone', 'zones', )

0👍

I found myself on this question. I was looking to write a test case that assertDictEqual. My mistake was looking at response.data instead of response.json(). response.data contained the OrderedDict since it hadn’t been rendered yet.

Leave a comment