DRF权限最佳实践DRY



当前在DRF中根据用户类型查看权限的最佳方式是什么?在我的结构中有几个user_types,例如TEAM_LEADER不能创建team对象,但可以看到teams的列表。这意味着对于同一个类视图,我希望使用不同的权限进行POST和GET。我希望尽可能干地做这件事,并试图遵循瘦视胖模型的设计原则(也想知道这是否是2021年的好做法(。

models.py用于用户模型


class User(AbstractBaseUser):
...fields here
objects = UserManager()
USERNAME_FIELD = "email"
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
if perm.Meta.verbose_name=="worksite" and perm.request.method =="POST":
if self.user_type <= self.DEPARTMENT_MANAGER:
return True
else:
return False
return True

视图.py


class DashboardPermissions(BasePermission):
message="You dont have permission for this action"
def has_permission(self, request, view):
return request.user.has_perm(view.Meta.verbose_name)
class ViewName(CreateAPIView):
permission_classes = (IsAuthenticated,DashboardPermissions)
authentication_classes = ()
serializer_class = WorksiteSerializer
queryset = Worksite.objects.all()
class Meta:
verbose_name="view_name"
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

奖金问题我的解决方案会产生任何性能问题吗?

创建自定义Permission类是一种很好的做法。所以这部分在我看来还可以。我们可以讨论逻辑应该在权限还是用户中(就像你做的那样(,但这没什么大不了的。

如果您希望对视图中的不同端点拥有不同的权限,只需覆盖get_permissions方法即可。

# Inherited method from APIView
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
return [permission() for permission in self.permission_classes]

正如您所看到的,对于ALL服务,它将从self.permission_classes获取权限。

要在GET/CREATE之间使用不同的权限,可以创建endpoint: [...permissions]dict,并覆盖get_permissions以获取与当前操作匹配的权限

permissions = {
"create": [P1, P2,],
"get": [P1,]
}
def get_permissions(self):
action = self.it_is_somewhere_in_there
return [permission() for permissions in self.permissions[action]]

@JordanKowal的回答是正确的,但正如评论中所提到的,

然后我会经常重复权限dict吗?为了做到这一点,每一类视图的权利

为此,您可以创建一个mixin类。它本质上允许您将要在多个视图中复制的一些代码/功能移动到一个独立的类中,并根据您的方便从中继承。

为了扩展Jordan的答案,以下是混合类的样子:

class DefaultPermissionsMixin(object):
permissions = {
"create": [IsAuthenticated, DashboardPermissions],
"get": [DashboardPermissions]
}

def get_permissions(self):
# default `get_permissions` method
# reads `self.permission_classes`
perms = super().get_permissions()
if self.action in self.permissions.keys():
return perms + [p() for p in self.permissions[self.action]]
else:
return perms


class View1(CreateAPIView, DefaultPermissionsMixin):
# ...snip...
class View2(CreateAPIView, DefaultPermissionsMixin):
# i can overwrite here per my convenience
permissions = {
"create": [DashboardPermissions],
"delete": [],
}
# i can also define permissions the default way
# that will be enabled on all actions
permission_classes = [IsAuthenticated]
# ...snip...

最新更新