I have models like this:
class TheModel(models.Model):
name = models.CharField(max_length=10)
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
TheModel
TheModel.owner
request.user
get_queryset
BasePermission
BasePermission.has_object_permission
BasePermission.has_permission
class TheModelViewSet(viewsets.ModelViewSet):
model = TheModel
permission_classes = [IsOwner]
class IsOwner(permissions.BasePermission):
def has_permission(self, request, view):
print("checking has permission for {}".format(request.user))
return True
def has_object_permission(self, request, view, obj):
print("checking permission for {} on {}").format(request.user, obj.user)
return obj.owner == request.user
IsOwner.has_permission
The official documentation recommends using a custom get_queryset
method in this use-case, and that's exactly what I would do.
The permission object's has_object_permission
only runs when called on a view for a single object, so that won't work to enforce permissions for list views.
Basically, you are not trying to allow or deny access, you are trying to filter the results. Filtering on a database level is the fastest, easiest and most secure (least error-prone) option. The permission framework is only made to either allow or deny access to an object or a complete object group, it is not made to filter the content of a particular response. The get_queryset
method is made to filter the content of a particular response, and should be used as such.