3👍
I think this can help you.
create serializer.py and write:
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'password')
and views.py:
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import UserSerializer
from .models import User
class AddUserAPIView(APIView):
def post(self, request):
user_serializer = UserSerializer(data=request.data)
if user_serializer.is_valid():
user = user_serializer.save()
user.set_password(user_serializer.data["password"])
return Response({'message': 'user added successfully!'})
return Response({'message': user_serializer.errors})
2👍
You are absolutely right!!:
APIView
doesn’t utilize a serializer_class
(by default) because it is not meant to handle any request processing logic!
What happens though is that the BrowsableAPIRenderer
that is used to render the API in the browser checks for a serializer_class
attribute and set’s it as the View serializer if it exists. We can see this in the BrowsableAPIRenderer
code:
-
The
_get_serializer
class of the renderer:def _get_serializer(self, serializer_class, view_instance, request, *args, **kwargs): kwargs['context'] = { 'request': request, 'format': self.format, 'view': view_instance } return serializer_class(*args, **kwargs)
-
And the way it is used to set the renderer serializer if it exists, inside the
get_rendered_html_form
:-
Line 483:
has_serializer_class = getattr(view, 'serializer_class', None)
-
if has_serializer: if method in ('PUT', 'PATCH'): serializer = view.get_serializer(instance=instance, **kwargs) else: serializer = view.get_serializer(**kwargs) else: # at this point we must have a serializer_class if method in ('PUT', 'PATCH'): serializer = self._get_serializer(view.serializer_class, view, request, instance=instance, **kwargs) else: serializer = self._get_serializer(view.serializer_class, view, request, **kwargs)
-
In essence, you accidentally override the BrowserAPIRenderer
‘s default behavior regarding the APIView
by providing the serializer_class
attribute. For what is worth, my opinion on the matter is that this should not be possible!
2👍
I use the django rest framework default get_schema_view()
to provide auto-generated openapi
schema from which I auto generate a javascript client for.
This works for ViewSets, but the payload wasn’t being provided for views defined by APIView
.
Where I have defined serializers, I found that adding get_serializer()
method to my APIView classes allowed the schema to be generated with the serializer defined payload.
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import UserSerializer
from .models import User
class AddUserAPIView(APIView):
def get_serializer(self, *args, **kwargs):
return UserSerializer(*args, **kwargs)
def post(self, request):
user_serializer = UserSerializer(data=request.data)
if user_serializer.is_valid():
user = user_serializer.save()
user.set_password(user_serializer.data["password"])
return Response({'message': 'user added successfully!'})
return Response({'message': user_serializer.errors})
- Return Custom 404 Error when resource not found in Django Rest Framework
- How to change my django server time
- Sending a message to a single user using django-channels
- Setting up proper testing for Django for TDD