简体   繁体   中英

How to filter user related records with permissions in Django Rest Framework

I need to know how to restrict access to Authenticated Users such that User Records can be listed in full for those logged in as Administrator and for those logged in as a User only their records can be listed, updated and created for themslefves.

Currently I am using serializers.ModelSerializer, viewsets.ModelViewSet and permissions.BasePermission but don't seem to be getting anywhere very fast.

There is no out of the box way of handling such permissions with a magic wand. Although there are some libraries out there that can handle object level permissions, check django-guardian as it has nice interface with Django rest Framework.

One good way to handle this is combine django-guardian's capabilities with a custom get_queryset() method as described by @ilse2005's answer. This takes care of your list and retrieve and update and deletion can be delegated to django-guardian .

class View(ModelViewSet):
    ...

    def get_queryset(self):
        if self.request.user.is_superuser:
            return FooModel.objects.all()
        return FooModel.objects.filter(owner=self.request.user)

This can also work with APIViews and other Class Based Views in DRF.

Caution : If your API consumers are relying on HTTP error codes for meaning this approach would throw them 404 not found instead of HTTP403 which is a standard way of saying permission denied. In this case it is advisable to write a custom permissions class. For example the following ip blacklisting permission class is straight from the documentation - http://www.django-rest-framework.org/api-guide/permissions/

from rest_framework import permissions

class BlacklistPermission(permissions.BasePermission):
    """
    Global permission check for blacklisted IPs.
    """

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists()
        return not blacklisted

Use this class in the viewset by setting up class variable

permission_classes = BlackListPermission

You can do that by overwriting the get_queryset method of the ModelViewSet :

class View(ModelViewSet):
    ...

    def get_queryset(self):
        if self.request.user.is_superuser:
            return FooModel.objects.all()
        return FooModel.objects.filter(owner=self.request.user)

This asumes that your FooModel has a ForeignKey attribute called owner to the UserModel

EDIT:

The above approach will only work for list and retrieve . For the update method you have to write a custom Permission.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM