pythondjangodjango-rest-frameworkbackenddocumentation

How does DRF de-serializes the json?


I am using react as frontend and django as backend. I have used fetch API to send send POST request to the server. The data is passed through JSON.stringify(). This request will be intercepted by views in Django and the data is available in request parameter of the view function. At least this is what I have understood. Now, when I access request.body, I surprisingly get a dict. It's surprising because serializer (which also the job of de-serializing) as yet to come in action. Then how did it got de-serialized automatically? And If this works somehow, then what is the need of introducing de-serializing functionality in serializer.

Frontend Code:

export async function AuthHandler(
    task,
    data,
    root_url
) {
    task = task==="login"?`${task}/`:''
    const resp = await fetch(`${root_url}${task}`, {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify(data), // what goes from here is string "{ }"
    });
    const respData = await resp.json();
    if (respData['token']){
        sessionStorage.setItem('token',respData['token'])

    }
    console.log(respData)
    return respData["token"];
}

Backend Code:

class GenericLoginView(generics.GenericAPIView):

    queryset = CustomUserModel.objects.all()
    serializer_class = UserLoginSerializer

    def post(self, request):
        token = None
        request_data = {
            "method": request.method,
            "headers": dict(request.headers),
            "body": request.data,
            "query_params": request.query_params,
            "path": request.path,
        }

        # Print the request as a dictionary
        print("Request as Dictionary:", request_data)
        print(type(request.data)) # dict
        serializer = self.serializer_class(data=request_data["body"])
        if serializer.is_valid():
            print(serializer.validated_data)
            email = serializer.validated_data["email"]
            password = serializer.validated_data["password"]
            user = authenticate(request, email=email, password=password)
            if user:
                token = Token.objects.get(user=user).key
        else:
            print(serializer.error_messages)
        return Response({"token": token})

Thanks in advance...

I tired checking the data type of the request.data. Also, looked upto the documentation.


Solution

  • While similar, these are actually two different processes that serve a different purpose. The reason your post request.body is a dict is actually due to the DRF Parser classes. These are applied before the request hits your view's post function. You can read more about these here https://www.django-rest-framework.org/api-guide/parsers/.

    Whereas the Serializer class is responsible for two main things:

    1. Serialization - Translating python objects (such as an instance of your CustomUserModel class) into a dictionary. This is primarily done when making a GET request since the django ORM will return a computed queryset (such as your CustomUserModel.objects.all()) as a list of CustomUserModel objects which cannot be directly turned into JSON to return to your frontend so is first passed through your serializer (using to_representation) to turn it into a dict which is JSON serializable

    2. De-serialization - Translating between a your response.data into validated data that can be used to create an instance of your CustomUserModel class. Primarily used during the POST or PATCH requests (uses to_internal_value method in your serializer)