Maxime B Maxime B - 6 months ago 105
Python Question

Django REST Framework ModelSerializer - Object not saved

I've a model, and one of it's field refers to an overrided User instance (changed in Django settings).

When I'm performing a POST from my client, the route ends up here at the

create
method:

class CatView(ModelViewSet):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
serializer_class = CatListSerializer

def get_queryset(self):
return Cat.objects.filter(owner=self.request.user).order_by('id')

'''
def list(self, request, format=None):
serializer = CatGetSerializer(Cat.objects.filter(owner=request.user), context={'request': request}, many=True)
return Response(serializer.data)
'''

def perform_create(self, serializer):
serializer.save(owner=self.request.user)

def create(self, request, *args, **kwargs):
serializer = CatPutSerializer(data=request.data)
if serializer.is_valid():
serializer.create(serializer.data)
return Response(serializer.data, status=HTTP_201_CREATED)
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)


When using a PUT to do a partial update on my model, it works fine. But creating one just doesn't work. I manually inject the
user
instance into the serializer and asks it to create the object. Then... nothing. No exception raises, it returns the proper data, but the object is not in my database, not being saved.

What's the issue here?

EDIT:

When I'm adding the
owner
field to the CatPutSerializer, it opens security issues since I don't know how to prevent this to be changed as I don't want the client to send me which user to assign. And when I'm duplicating the serializer to be used on POST only requests, it says it misses the
owner
field...

Here's the
CatPutSerializer
:

class CatPutSerializer(serializers.ModelSerializer):
class Meta:
model = Cat
fields = ('name', 'weight', 'sterilized', 'image', 'tag', 'dob', 'race', 'gender')


UPDATE:

As suggested, I'm now doing as follows :

def create(self, request, *args, **kwargs):
pdb.set_trace()
serializer = CatPutSerializer(data=request.data)
if serializer.is_valid():
serializer.save(owner=self.request.user)
return Response(serializer.data, status=HTTP_201_CREATED)
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)


Though removed the
perform_create
overriding.

SOLUTION:

After further investigation, it doesn't seem related to
drf
but to Django / PostgreSQL itself, so I checked to Django model
save
method, and it seems that my custom image processing prevented from new objects to be created... Changed it and now works.

Answer

You seem to be overriding both create and perform_create. If you look at the code for CreateModelMixin which the ModelViewSet inherits from you will notice that create calls perform_create, which calls serializer.save(). You don't call perform_create in your create method; you seem to be calling serializer.create(...). If you are overriding create, simply do this:

def create(self, request, *args, **kwargs):
    serializer = CatPutSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save(owner=self.request.user)
        return Response(serializer.data, status=HTTP_201_CREATED)
    return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
Comments