Reputation: 4110
I'm trying to update a profile object with post method, but I get a error message when trying to save my serializer :
You cannot call `.save()` after accessing `serializer.data`.If you need to access data before committing to the database then inspect 'serializer.validated_data' instead.
My view :
class SettingsProfileView(APIView):
"""
Get and update user profile
"""
queryset = models.UserProfile.objects.all()
serializer_class = serializers.UserProfileSerializer
renderer_classes = [TemplateHTMLRenderer]
template_name = 'base_/settings/profile.html'
def get_object(self, pk):
try:
return models.UserProfile.objects.get(pk=pk)
except models.UserProfile.DoesNotExist:
raise Http404
def get(self, request, format=None):
if not request.user.is_authenticated:
return Response({"error": _("User is not connected")}, status=status.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED)
try:
profile = request.user.profile
except models.UserProfile.DoesNotExist:
profile = models.UserProfile(user=request.user)
profile.key_name = request.user.username
profile.save()
profile = self.get_object(request.user.profile.id)
serializer = serializers.UserProfileSerializer(profile)
return Response({'serializer': serializer, 'profile': profile})
def post(self, request, format=None):
serializer = serializers.UserProfileSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
The error occured in this part : serializer.save()
in my post method. Is it because the serializer is accessing data in his instentiation method ?
My serializer is very basic, it has no special code :
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('user', 'coachs', 'is_coach', 'gender', 'weight', 'height', 'visibility', )
Maybe the problem comes from the fact that I'm using post methode instead of update ?
EDIT (after @pleasedontbelong post) :
I've tried with generic view :
class SettingsProfileView(generics.GenericAPIView):
but the update method is not fired (because I come from a HTML post), so I had to manually raise update method like that :
def post(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object(request.user.profile.id)
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
But the error is still the same. I cannot find any example where an object is updated with django rest by post method. Is it because it's not a good way to proceed ?
Upvotes: 1
Views: 2307
Reputation: 4110
After hours of debugging, it appear that the problem comes from Visual Studio's breakpoints. After removing breakpoints it works fine. Maybe Visual Studio try to read in serializer.data and then affects them.
Upvotes: 4
Reputation: 20102
It's better to use generic views, it prevents you from rewriting all this code. But if you rather do it manually, you can always check the source code to check how it's done:
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py#L61-L78
class UpdateModelMixin(object):
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
def perform_update(self, serializer):
serializer.save()
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
you must pass the UserProfile instance to the serializer
BTW: you should/must use PUT or PATCH for updating, POST is for creating objects.
Hope this helps :)
Upvotes: 0