Побитовое решение:
Как насчет создания собственного IsAdminUser
, который также определяет has_object_permission
?Вы можете просто унаследовать от существующего:
from rest_framework.permissions import IsAdminUser as BaseIsAdminUser
class IsAdminUser(BaseIsAdminUser):
def has_object_permission(self, request, view, obj):
# Just reuse the same logic as `has_permission`...
return self.has_permission(request, view)
Затем вы можете сделать то, что вы пытались выше, с помощью побитового оператора:
from rest_framework import permissions, viewsets
from your_own_project.permissions import IsAdminUser
class SomeModelViewSet(viewsets.ModelViewSet):
permission_classes = (IsAdminUser|SomeModelPermission,)
Другое решение:
В некотором смысле немного "хакерский", но вы можете попытаться создать свои собственные типы разрешений на лету.
Таким образом, конечный результат будет выглядеть примерно так:
class SomeModelViewSet(viewsets.ModelViewSet):
permission_classes = skip_for_staff((SomeModelPermission, SomeOtherPermission, ...))
С реализацией, похожей на:
class StaffAllowedMixin:
def has_permission(self, request, view):
if request.user.is_staff:
return True
return super().has_permission(request, view)
def has_object_permission(self, request, view, obj):
if request.user.is_staff:
return True
return super().has_object_permission(request, view, obj)
def skip_for_staff(permission_classes):
# You can probably also use a comprehension here, but for clarity:
staff_allowed_classes = []
for permission_class in permissions(
staff_allowed_classes.append(
# Create a new type (class) with name StaffAllowed<...>
type(f"StaffAllowed{permission_class}",
# Inherit from the mixin above, and from the original class
(StaffAllowedMixin, permission_class),
# empty dictionary means you don't want to override any attributes
{})
)
return tuple(staff_allowed_classes)
По существу, для каждого класса разрешений вы создаете новый класс с дополнительным миксином, который имеет приоритет и проверяет, является ли пользователь персоналом.Но вы делаете это на лету, где используются ваши разрешения, вместо того, чтобы предопределять его для каждого разрешения.