List-only filter in ModelViewset

276 views
Skip to first unread message

Raúl Pedro Santos

unread,
Jan 19, 2016, 6:24:31 PM1/19/16
to Django REST framework
Hi everyone,

Is there a way, when using a ModelViewSet, to filter only the list results but not the detail results?

I have a list of objects that have an owner and I only want users to see the ones they own when they access the objects list. For that purpose I implemented a new permission class based on rest_framework.permissions.BasePermission, which works fine with the list.

The problem arises when I try to access an object that doesn't belong to my user: I get a "404 not found" instead of a "403 forbidden".

In other words, filtering seems to be applied not only to the list but also to the detail view. Is there a way to change this, so that I get the expected 403 when accessing an object which I'm not authorized to see?

Thanks,
Raúl

Raúl Pedro Santos

unread,
Jan 19, 2016, 6:46:27 PM1/19/16
to Django REST framework
Sorry, I meant to say that I implemented a new filter based on filters.BaseFilterBackend, not a new permission (which I also did but that's a different matter).

Xavier Ordoquy

unread,
Jan 20, 2016, 1:46:01 AM1/20/16
to django-res...@googlegroups.com
Hi
You could override the get_object and remove the call to filter_queryset (https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/generics.py#L84).

Regards,
Xavier,
Linovia.

Raúl Pedro Santos

unread,
Jan 20, 2016, 7:02:56 AM1/20/16
to Django REST framework
Hi Xavier,

That sounds like it could work. I would have to do it for every one of the models I'm exposing through the API, though, and there are a lot of them, which would make this quite a cumbersome task.

I would also prefer not to override the entire method, since I still want to rely on DRF's code and future changes (my overridden method may become incompatible with DRF for some reason).

I was hoping for something like a property I could set on my ModelViewSet, something like "list_view_filter_backends" and those would only be applied to the list view but I don't think such a thing exists at all.

Another option would be for me to remove the filter_backends property from my ViewSet class and then override the list() method, but that brings me back to my first two points against overriding get_object().

Of course ultimately I could not use ViewSets and do things manually but I would obviously also prefer not to do that, since I'm rather fond of how much work DRF saves me with the ViewSets.

Not sure what to do here...

Raúl

Raúl Pedro Santos

unread,
Jan 20, 2016, 7:26:06 AM1/20/16
to Django REST framework
Another way to think about this is that I only want to list objects that the user has permission to see. Maybe this brings up other options.


On Tuesday, 19 January 2016 23:24:31 UTC, Raúl Pedro Santos wrote:

Xavier Ordoquy

unread,
Jan 20, 2016, 7:29:08 AM1/20/16
to django-res...@googlegroups.com
Hi Raúl

Le 20 janv. 2016 à 13:02, Raúl Pedro Santos <bor...@gmail.com> a écrit :

Hi Xavier,

That sounds like it could work. I would have to do it for every one of the models I'm exposing through the API, though, and there are a lot of them, which would make this quite a cumbersome task.

You could define a mixin for that. It’ll keep all the change in one place.

I would also prefer not to override the entire method, since I still want to rely on DRF's code and future changes (my overridden method may become incompatible with DRF for some reason).

I know how this feels. Alternatively, you could override the `filter_query` and, based on the mapping, call the super().filter_query or not, probably through the view set’s self.actions

I was hoping for something like a property I could set on my ModelViewSet, something like "list_view_filter_backends" and those would only be applied to the list view but I don't think such a thing exists at all.

Another option would be for me to remove the filter_backends property from my ViewSet class and then override the list() method, but that brings me back to my first two points against overriding get_object().

Of course ultimately I could not use ViewSets and do things manually but I would obviously also prefer not to do that, since I'm rather fond of how much work DRF saves me with the ViewSets.

Not sure what to do here...

Raúl


On Wednesday, 20 January 2016 06:46:01 UTC, Xavier Ordoquy wrote:
Hi 

> Le 20 janv. 2016 à 00:24, Raúl Pedro Santos <bor...@gmail.com> a écrit : 
> 
> Hi everyone, 
> 
> Is there a way, when using a ModelViewSet, to filter only the list results but not the detail results? 
> 
> I have a list of objects that have an owner and I only want users to see the ones they own when they access the objects list. For that purpose I implemented a new permission class based on rest_framework.permissions.BasePermission, which works fine with the list. 
> 
> The problem arises when I try to access an object that doesn't belong to my user: I get a "404 not found" instead of a "403 forbidden". 
> 
> In other words, filtering seems to be applied not only to the list but also to the detail view. Is there a way to change this, so that I get the expected 403 when accessing an object which I'm not authorized to see? 

You could override the get_object and remove the call to filter_queryset (https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/generics.py#L84). 

Regards, 
Xavier, 
Linovia.

-- 
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages