2

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.

6
  • Are you trying to create using PUT? Commented May 27, 2016 at 16:17
  • No, actually the serializer is the same for PUT and POST with partial and non partial arguments, tough I should change its name. Commented May 27, 2016 at 16:24
  • Well, it looks ok to me, haha. Can you please post a sample request and the response you get back even when the data is not saved? Commented May 27, 2016 at 16:30
  • Here it is : Sending as multipart/form-data: dob: "1997-01-07" gender: "M" image: null name: "aze" race: "Devon Rex" sterilized: false tag: "null" weight: 23 Receiving : 201 Created / application/json {"name":"aze","weight":23,"sterilized":false,"image":null,"tag":"null","dob":"1997-01-07","race":"Devon Rex","gender":"M"} Commented May 27, 2016 at 16:32
  • As you go through the debugger, you should see if the execution ever reaches the serializer.save() step (put a breakpoint there), because that is where the db save happens. If it does not, you'd know where the problem is and you can work on that so that it hits serializer.save. If it hits serializer.save() then the question is did you override your serializer's save method? Commented May 31, 2016 at 15:54

1 Answer 1

4

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)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer! That's the way I tried to do it in the first place, and wasn't working aswell. I removed the perform_create overriding. Did I miss something? I'll add my serializer as an edit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.