Jeet Patel
Jeet Patel

Reputation: 1241

Unable to get the response for POST request to APIView of Django Rest-framework

I am sending the post request to OrganisationApiView class. The request body contains the following JSON.

{
"organisation_id" : "1",
"organisation_name" "Some Name"
}

views.py

from typing import Optional, Any
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.parsers import JSONParser

from . import serializers


class OrganisationApiView(APIView):

    serializers_class = serializers.OrganisationSerializer
    parser_classes = [JSONParser]

    def get(self, request, formate=None):
        return Response({"message": "You are Cool!!"})

    def post(self, request, formate=None):
        serializer = self.serializers_class(data=request.data)
        print(serializer)

        if serializer.is_valid():
            organisation_name = serializer.validated_data.get('organisation_name')
            message = f"Reached POST {organisation_name}"
            return Response({'message': message, status: 'HTTP_200_OK'})
        else:
            return Response(
                serializer.errors,
                status=status.HTTP_400_BAD_REQUEST
            )

    def put(self, request, pk=None):
        return Response({"message": "PUT"})

    def patch(self, request, pk=None):
        return Response({"message": "PATCH"})

    def delete(self, request, pk=None):
        return Response({"message": "Delete"})

I get the response on postman as -

TypeError at /api/organisation/
keys must be str, int, float, bool or None, not module
Request Method: POST
Request URL:    http://127.0.0.1:8000/api/organisation/
Django Version: 2.1.15
Exception Type: TypeError
Exception Value:    
keys must be str, int, float, bool or None, not module
Exception Location: /usr/local/lib/python3.7/json/encoder.py in iterencode, line 257
Python Executable:  /usr/local/bin/python
Python Version: 3.7.6
Python Path:    
['/app',
 '/usr/local/lib/python37.zip',
 '/usr/local/lib/python3.7',
 '/usr/local/lib/python3.7/lib-dynload',
 '/usr/local/lib/python3.7/site-packages']
Server time:    Sat, 4 Jan 2020 06:42:54 +0000

Other requests like GET, PUT, PATCH, DELETE are working just fine. I don't understand what exactly has caused this problem. I have also defined the SimpleSerializers as stated below.

from rest_framework import serializers
class OrganisationSerializer(serializers.Serializer):
    organisation_id = serializers.IntegerField()
    organisation_name = serializers.CharField(max_length=255, allow_null=False, allow_blank=False)

Also, I don't want to accept the organisation_id as in the models I have defined it as Primary Key. But when I send the JSON without organisation_id it raises an error stating field organisation_id is required. As of now I just want to accept the organisation_name and return it in response.

Upvotes: 1

Views: 1938

Answers (1)

engin_ipek
engin_ipek

Reputation: 917

You are trying to return serializer.errors as JSON data, but it is not a dictionary, it is a module. You can use serializer.error_messages instead.

Try this:

else:
    return Response(
        serializer.error_messages,
        status=status.HTTP_400_BAD_REQUEST
    )

Better Solution

Since you are only trying to return the details of the serializing process, When calling serializer's is_valid function, you can pass a parameter to trigger an exception if the serializer is not valid. serializer.is_valid(raise_exception=True). Its default format will satisfy your needs. The code will be:

def post(self, request, formate=None):
    serializer = self.serializers_class(data=request.data)
    serializer.is_valid(raise_exception=True)
    organisation_name = serializer.validated_data.get('organisation_name')
    message = f"Reached POST {organisation_name}"
    return Response({'message': message, status: 'HTTP_200_OK'})

Upvotes: 1

Related Questions