Search code examples
pythondjangodjango-rest-frameworkdjango-serializer

Use orjson/ujsonin drf


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


Solution

  • 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)