在视图中定义权限时,我想始终检查请求用户是否具有该权限。
假设我有这样的基本权限检查:
class HasPermission(permissions.BasePermission):
def has_permission(self, request, view, obj=None):
if hasattr(view, 'permission_required'):
return request.user.has_perm(view.permission_required)
return True
我已将其添加为我的
settings
中的默认权限:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
),
'DEFAULT_PERMISSION_CLASSES': [
'apps.api.permissions.HasPermission'
],
}
这是可行的,但是一旦我在视图中定义了
permission_classes
,默认值就会被覆盖。有没有干净且正确的方法来做到这一点?我可能可以编写一个 Mixin 并在 dispatch
中执行相同的操作,但想使用推荐的 Permission
类。
权限属性采用类列表,因此您只需包含默认值即可。
class ModelViewSet(viewsets.ModelViewSet):
permission_classes = (
DefaultPermission,
CustomPermission,
)
permission_classes
时,才会应用DEFAULT_PERMISSION_CLASSES。
如果您没有任何其他需要申请的权限类别,只需从您的视图集中排除
permission_classes
,这样它将始终使用默认值。
如果有时您需要使用其他权限类别以及默认权限类别。
例如
class HasPermission(permissions.BasePermission):
def has_permission(self, request, view, obj=None):
if hasattr(view, 'permission_required'):
return request.user.has_perm(view.permission_required)
return True
class AnotherPermissionClass(..):
....
其中
HasPermission
始终需要应用,有时可能还需要应用 AnotherPermissionClass`。
如果是这种情况,那么只需继承
HasPermission
作为 AnotherPermissionClass
的基类即可。
AnotherPermissionClass(apps.api.permissions.HasPermission)
def has_permmision(self, request, view, obj=None):
has_base_perm = super().has_permmision(request, view, obj=obj)
...
class ViewsetA(...):
...
# Don't declare permission_classes at all and it will use the settings default
class ViewsetB(...):
permission_classes = (AnotherPermissionClass,)
这更加灵活,因为根据项目的不同,将来可能会有一组完全不同的 API(或者可能根本没有)。
permission_classes
您可以创建一个辅助函数,以便更容易使用
from rest_framework import permissions
from rest_framework.settings import api_settings
class MyView(viewsets.ModelViewSet):
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES + [permissions.IsAdminUser]
from rest_framework import permissions
from rest_framework.settings import api_settings
def init_perms(new_classes: list) -> list:
return api_settings.DEFAULT_PERMISSION_CLASSES + new_classes
class MyView(viewsets.ModelViewSet):
permission_classes = init_perms([permissions.IsAdminUser])
并从中间件读取视图类属性以了解是否运行默认的。