What are DRF Renderers & Parsers?

Overlook

  • Just Django

 

  • Django (DRF) + React

 

  • Django (DRF) + React + Redux (sagas, router, etc.)

here

Python

snake_case

JavaScript

camelCase

Solutions

  1. JS Utils
  2. React middleware
  3. DRF's Renderer & Parser

How do they look?

CamelCaseRenderer

from rest_framework import renderers

from project_name.common.cases import deep_camel_case_transform


class CamelCaseRenderer(renderers.JSONRenderer):
    def render(self, data, *args, **kwargs):
        camelized_data = deep_camel_case_transform(data)

        return super().render(camelized_data, *args, **kwargs)

You love DRF's templates?

from rest_framework import renderers

from project_name.common.cases import deep_camel_case_transform


class CamelCaseRenderer(renderers.JSONRenderer):
    def render(self, data, *args, **kwargs):
        camelized_data = deep_camel_case_transform(data)

        return super().render(camelized_data, *args, **kwargs)


# Use this one in your APIs if you want the DRF's template view
class BrowsableCamelCaseRenderer(renderers.BrowsableAPIRenderer):
    def get_default_renderer(self, view):
        return CamelCaseRenderer()

SnakeCaseParser

from rest_framework import parsers

from project_name.common.cases import deep_snake_case_transform


class SnakeCaseParser(parsers.JSONParser):
    def parse(self, stream, *args, **kwargs):
        data = super().parse(stream, *args, **kwargs)

        return deep_snake_case_transform(data)

Put them in Mixins!

from rest_framework import renderers

from .renderers import BrowsableCamelCaseRenderer, CamelCaseRenderer
from .parsers import SnakeCaseParser


class ToCamelCase(renderers.BrowsableAPIRenderer):
    renderer_classes = (BrowsableCamelCaseRenderer, CamelCaseRenderer, )


class FromCamelCase:
    parser_classes = (SnakeCaseParser, )

Usage

Retrive/List APIs

from rest_framework import serializers
from rest_framework.generics import RetrieveAPIView

from project_name.apis.mixins import ToCamelCase


class ObjectRetrieveSerializer(serializers.ModelSerializer):
    class Meta:
        model = Object
        fields = (snake_case_field_name, )


class ObjectRetrieveAPI(ToCamelCase, RetrieveAPIView):
    serializer_class = ObjectRetrieveSerializer
    queryset = Object.objects.all()
    lookup_url_kwarg = 'object_id'



# Will return `{'snakeCaseFieldName': 'value'}` in it's Response

Create/Update APIs

from rest_framework import serializers
from rest_framework.generic import CreateAPIView

from project_name.apis.mixins import FromCamelCase


class ObjectCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Object
        fields = (snake_case_field_name, )


class ObjectCreateAPI(FromCamelCase, CreateAPIView):
    serializer_class = ObjectCreateSerializer
    queryset = Object.objects.all()



# Will handle `{'snakeCaseFieldName': 'value'}` in the Request

Use them together

from rest_framework import serializers, status
from rest_framework.response import Response
from rest_framework.views import APIView

from project_name.apis.mixins import FromCamelCase, ToCamelCase


class ObjectCreateAPI(FromCamelCase, ToCamelCase, APIView):
    def post(self, request, *args, **kwargs):
        serializer = ObjectCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        # perform create here ...

        output_data = ObjectRetrieveSerializer(created_instance).data

        return Response(output_data, status=status.HTTP_201_CREATED)



# Will hadnle `{'snakeCaseFieldName': 'value'}` in the Request
# Will return the created object in the format `{'snakeCaseFieldName': 'value'}`

Thank you!

GH: https://github.com/martin056

Twitter: https://twitter.com/_martin056

Email: martin.angelov@hacksoft.io

https://www.hacksoft.io/blog/how-to-deal-with-cases-mismatch-between-django-and-react/

Blog Post

Made with Slides.com