Django Rest 框架权限和所有权

And*_*ara 4 python django django-rest-framework

我有两个简单的模型

class User(AbstractUser): 
    pass


class Vacation(Model):
    id    = models.AutoField(primary_key=True)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
Run Code Online (Sandbox Code Playgroud)

我不太确定对 Django Rest Framework 进行用户权限的可扩展方式是什么。特别是:

  • 用户应该只能看到自己的假期
  • 在/vacation端点上,用户将看到一个过滤列表
  • 在/vacation/$id端点上,用户将获得一个403if not owner
  • 用户应该只能创建/更新假期,只要他们是该对象的所有者(通过外键)

以面向未来的方式实现这一目标的最佳方法是什么?如果进一步说:

  • 我添加了不同的用户类型,可以查看所有假期,但只能创建/更新/删除自己的
  • 我添加了另一个模型,用户可以读,但不能写

谢谢!

meh*_*sum 6

从文档:

REST framework 中的权限始终定义为权限类列表。在运行视图主体之前,检查列表中的每个权限。如果任何权限检查失败,将引发 exceptions.PermissionDenied 或 exceptions.NotAuthenticated 异常,并且视图的主体将不会运行。

REST 框架权限还支持对象级权限。对象级别权限用于确定是否应允许用户对特定对象(通常是模型实例)进行操作。

对于您当前的需要,您可以定义自己的 Permission 类:

class IsVacationOwner(permissions.BasePermission):
    # for view permission
    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated

    # for object level permissions
    def has_object_permission(self, request, view, vacation_obj):
        return vacation_obj.owner.id == request.user.id
Run Code Online (Sandbox Code Playgroud)

并将此权限添加到您的视图中。例如在视图集上:

class VacationViewSet(viewsets.ModelViewSet):
    permission_classes = (IsVacationOwner,)
Run Code Online (Sandbox Code Playgroud)

这里要注意一件事很重要,因为您将使用 的过滤列表进行响应'/vacations',请确保使用request.user. 因为对象级权限不适用于列表。

出于性能原因,通用视图在返回对象列表时不会自动将对象级别权限应用于查询集中的每个实例。

对于您未来的需求,您始终可以借助get_permissions方法有条件地设置权限。

class VacationViewSet(viewsets.ModelViewSet):
    def get_permissions(self):
        if self.action == 'list':
            # vacations can be seen by anyone
            # remember to remove the filter for list though
            permission_classes = [IsAuthenticated] 

            # or maybe that special type of user you mentioned
            # write a `IsSpecialUser` permission class first btw
            permission_classes = [IsSpecialUser] 
        else:
            permission_classes = [IsVacationOwner]

        return [permission() for permission in permission_classes]
Run Code Online (Sandbox Code Playgroud)

DRF 有很好的文档。我希望这可以帮助您入门并帮助您根据未来的需求处理不同的用例。


Mar*_*ddy -1

Django Rest 框架为此提供了内置设置

只需导入所需的权限并将其添加到您的类变量permission_classes中

在my_name.api.views中

from rest_framework.permissions import ( AllowAny, IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly,)

class Vacation(ListAPIView):
    serializer_class = VacationListSerializer
    permission_classes = [IsAuthenticated]
Run Code Online (Sandbox Code Playgroud)

您可以将多个权限类别添加为列表

此外,如果这没有帮助,您始终可以将模型对象过滤为

Mymodel.objects.filter(owner = self.request.user)
Run Code Online (Sandbox Code Playgroud)