Django REST 权限类不能在 OR 中一起工作,而是按预期独立工作
Posted
技术标签:
【中文标题】Django REST 权限类不能在 OR 中一起工作,而是按预期独立工作【英文标题】:Django REST permission classes don't work together inside an OR but work as expected independently 【发布时间】:2021-08-13 05:15:45 【问题描述】:我在使用 OR 运算符将两个权限放在一起时遇到了麻烦。文档说: Doc
如果它们从 rest_framework.permissions.BasePermission 继承,则可以使用标准 Python 位运算符组合权限。例如,IsAuthenticatedOrReadOnly 可以写成: ... permission_classes = [IsAuthenticated|ReadOnly]
所以我创建了权限:
permissions.py
class IsFullUserOrReadOnly(permissions.BasePermission):
"""
This class defines the permission to only allow the request to certain users with a
certain role."""
def has_permission(self, request, view):
"""
This function overrides the default has_permission method to allow the writing methods
only to full users or admin users
"""
if request.method in permissions.SAFE_METHODS:
return True
is_full_user = False
queryset = User.objects.get(email=request.user)
if queryset:
user = UserSerializer(queryset)
if 'roles' in user.data:
for role in user.data['roles']:
if role == ADMIN or role == FULL_USER:
is_full_user = True
print('IsFullUserOrReadOnly')
print(is_full_user)
print(request.method)
print(request.method =='POST')
return is_full_user or request.method =='POST'
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
This class defines the permission to only allow the POST and PUT methods to the creator of
the item."""
def has_object_permission(self, request, view, obj):
"""
This function overrides the default has_object_permission method to allow the writing
methods to the owner of the object
"""
if request.method in permissions.SAFE_METHODS:
return True
# Instance must have an attribute named `created_by`.
print('IsOwnerOrReadOnly')
print(obj.created_by == request.user)
return obj.created_by == request.user
然后我将它们添加到我的视图中:
view.py
class ItemViewset(viewsets.ModelViewSet): # pylint: disable=too-many-ancestors
"""API Endpoint to return the list of items"""
queryset = Item.objects.all()
serializer_class = ItemSerializer
# permission_classes = (IsAuthenticated, IsFullUserOrReadOnly,)
permission_classes = [IsAuthenticated, IsFullUserOrReadOnly|IsOwnerOrReadOnly,]
# permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
permission_classes
的两条注释行按预期工作,但是当我尝试将它们一起使用时,这意味着,作为一个完整用户或非安全方法的所有者,它总是允许一切。好像没有条件了。
我不知道我是否遗漏了什么,但据我所知,这应该可行。我错过了什么吗?
【问题讨论】:
【参考方案1】:经过一些研究,我发现在这个link 中报告了一个错误。作为一种解决方法,我将以下方法添加到IsFullUserOrReadOnly
:
def has_object_permission(self, request, view, obj):
"""
This function overrides the default has_object_permission to prevent the bug documented in:
https://github.com/encode/django-rest-framework/issues/7117
"""
return self.has_permission(request, view)
然后我将顺序切换为:
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly|IsFullUserOrReadOnly,)
而且似乎确实可以解决问题
【讨论】:
以上是关于Django REST 权限类不能在 OR 中一起工作,而是按预期独立工作的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Django Rest Framework 过滤器将过滤器链接在一起
python Django Rest_Framework框架 认证权限限流功能组件详解(图文并茂版)
python Django Rest_Framework框架 认证权限限流功能组件详解(图文并茂版)