Can't seem to return Response with error status when overriding perform_update on ModelViewSet

842 views
Skip to first unread message

Howie Weiner

unread,
Jan 20, 2015, 6:21:59 AM1/20/15
to django-res...@googlegroups.com
Hi

I need to perform a pre_save check prior to updating a model. The check requires access to the session user, so I thought that the perform_update method on ModelViewSet would be a good place for the code.

My code is as follows:

def perform_update(self, serializer):
        user = self.request.user
        order = self.get_object()
        
        if user.is_customer and order.status not in (Order.STATUS.unallocated, Order.STATUS.authorised,):
            return Response(status=status.HTTP_403_FORBIDDEN)
        serializer.save()

The code executed as expected, however, a 403 is not returned? Can't see why? I've looked at the code in UpdateModelMixin and there is nothing to suggest why this wouldn't work

However, if I override the actual update method, I can throw a 403. I guess the fact that serializer.is_valid() has not thrown an exception, is the reason, though I would expect to be able to return an HTTP Response of my liking at any point?

What am I missing? Is there a better place to validate the user against the model? I guess I could add a method to the serializer to set the session user, and modify the update method to check against this, hence throwing a validation error.. though this is more a security check

thnx

Tom Christie

unread,
Jan 20, 2015, 7:09:09 AM1/20/15
to django-res...@googlegroups.com
> though I would expect to be able to return an HTTP Response

Don't expect that - that override hook isn't intended to return any value or response.


> I can throw a 403

If 403 is the response you want, then that's a perfectly acceptable thing to do, sure.
Nothing particularly wrong with putting that sort of logic in the view code, although...

> this is more a security check

...so the best thing to do is probably to put the check in a custom Permission class as an object-level permission check.
You have the order (the object being checked) and the user (as part of the request) available during those checks so you've got everything you need to correctly ensure the user has permissions to update that object.

There's an example of a custom object-permission here: http://www.django-rest-framework.org/api-guide/permissions/#examples

Hope that helps,

  Tom

Howie Weiner

unread,
Jan 20, 2015, 7:39:35 AM1/20/15
to django-res...@googlegroups.com

of course! thank you. I'm already using custom permission classes.. completely missed the object level check. Perfect

thank you, as always
Reply all
Reply to author
Forward
0 new messages