Use orjson/ujsonin drf

506 views Asked by At

Hi all im looking into faster ways of returning JSON data etc. I know that FastAPI uses

ujson
orjson

Is there a way to replace the standard drf serializer to orjson?

edit Lets say i have this viewset

class ProfileViewSet(viewsets.ModelViewSet):
    permission_classes = [ProfilePermission]
    serializer_class = ProfileSerializer
    pagination_class = ProfilePagination
    filterset_class  = ProfileFilter

    def get_queryset(self):

        current_id = self.request.user.id
        blocked_users = Blocked.objects.filter(user__id=current_id).values('blocked')

        users_taken_action = Action.objects.filter(user__id=current_id).values('action_user')

        users_not_taken_action = Profile.objects.exclude(user__in=users_taken_action) \
            .exclude(user__in=blocked_users).exclude(user__id=current_id)

        
        return users_not_taken_action

and this serializer

class ProfileSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
    
    fav_data = serializers.SerializerMethodField(read_only=True)
    images = serializers.SerializerMethodField(read_only=True)
    user = UserSerializer(read_only=True)
    place = PlaceSerializer(read_only=True)
    

    def get_images(self, obj):
        return PhotoSerializer(UserPhoto.objects.filter(user=obj.user.id), many=True).data

    def get_fav_data(self, obj):
        fav_data = Favorite.objects.get(user=obj.user.id).data
        
        return {
            "id": fav_data.id,
            "name": fav_data.name,
            "category": fav_data.category,
        }

    class Meta:
        model = Profile
        fields = '__all__'
        depth = 1
        

How can I convert it to ojson/urjson

2

There are 2 answers

3
COSHW On BEST ANSWER

I've made a file like that in my utils (required orjson package):

try:
    import orjson as json
except ImportError:
    import json

from django.http import HttpResponse


class ORJsonResponse(HttpResponse):
    def __init__(self, data, safe=True, json_dumps_params=None, load=False, **kwargs):
        if safe and not isinstance(data, dict) and not load:
            raise TypeError(
                'In order to allow non-dict objects to be serialized set the '
                'safe parameter to False.'
            )
        if load and safe and not isinstance(data, (bytes, bytearray, str)):
            raise TypeError(
                'In order to allow non-bytes objects to be sent set the '
                'safe parameter to False.'
            )
        if json_dumps_params is None:
            json_dumps_params = {}
        kwargs.setdefault('content_type', 'application/json')
        if not load:
            data = json.dumps(data, **json_dumps_params)
        super().__init__(content=data, **kwargs)

And used ORJsonResponse instead of default Response.

    def create(self, request, *args, **kwargs):
        response = super().create(request, *args, **kwargs)
        return ORJsonResponse(response.data)
0
Sanyam Khurana On

You can use the drf-orjson-renderer package along with DRF.

Install it via pip install drf-orjson-renderer and then you can configure all your REST_FRAMEWORK APIs to use that renderer and parser as follows:

REST_FRAMEWORK = {
    "DEFAULT_RENDERER_CLASSES": (
        "drf_orjson_renderer.renderers.ORJSONRenderer",
        "rest_framework.renderers.BrowsableAPIRenderer",
    ),
    "DEFAULT_PARSER_CLASSES": (
        "drf_orjson_renderer.parsers.ORJSONParser",
    ),
}

Furthermore, to modify how data is serialized, specify options in your settings.py

REST_FRAMEWORK = {
    "ORJSON_RENDERER_OPTIONS": (
        orjson.OPT_NON_STR_KEYS,
        orjson.OPT_SERIALIZE_DATACLASS,
        orjson.OPT_SERIALIZE_NUMPY,
    ),
}

Using ORJSON as a parser and renderer gives a performance boost to your APIs and is a quick win!