lWh*_*ore 31 python django django-permissions django-rest-framework
我是使用Django + Django Rest-framework进行开发的新手,我正在开发一个提供REST Api访问的项目.我想知道为给定的ApiView或Viewset的每个动作分配不同的权限是什么最佳做法.
假设我定义了一些权限类,例如'IsAdmin','IsRole1','IsRole2',...,我想为单个操作授予不同的权限(例如,具有Role1的用户可以创建或检索用户, Role2可以更新,只有管理员可以删除).
如何构建基于类的视图,以便为"创建","列表","检索","更新","删除"操作分配权限类?我试图这样做有一个类可以重用于具有相同权限模式的不同表.
也许我只是淹死在一寸水里,谢谢你的回复.
Che*_*mer 50
在DRF文档中,
注意:只有在视图级别has_permission检查已通过时才会调用实例级别的has_object_permission方法
让我们假设关于user
对象的以下许可
permissons.py
from rest_framework import permissions
class UserPermission(permissions.BasePermission):
def has_permission(self, request, view):
if view.action == 'list':
return request.user.is_authenticated() and request.user.is_admin
elif view.action == 'create':
return True
elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
return True
else:
return False
def has_object_permission(self, request, view, obj):
# Deny actions on objects if the user is not authenticated
if not request.user.is_authenticated():
return False
if view.action == 'retrieve':
return obj == request.user or request.user.is_admin
elif view.action in ['update', 'partial_update']:
return obj == request.user or request.user.is_admin
elif view.action == 'destroy':
return request.user.is_admin
else:
return False
Run Code Online (Sandbox Code Playgroud)
views.py
from .models import User
from .permissions import UserPermission
from .serializers import UserSerializer
from rest_framework import viewsets
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (UserPermission,)
Run Code Online (Sandbox Code Playgroud)
编辑
Django的2.0替换is_authenticated()
用is_authenticated
.该方法已变为属性.
Car*_*son 16
您可以创建扩展DRF的自定义权限类BasePermission
.
您可以has_permission
在有权访问request
和view
对象的位置实现.您可以检查request.user
适当的角色并根据需要返回True
/ False
.
看看提供的IsAuthenticatedOrReadOnly类(以及其他类),看看它是多么容易的好例子.
我希望有所帮助.
Lau*_*det 14
从DRF 文档中,您现在可以这样做:
装饰器允许您覆盖任何视图集级别的配置,例如permission_classes、serializer_class、filter_backends...:
@action(detail=True, methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
Run Code Online (Sandbox Code Playgroud)
小智 5
我个人讨厌这种Frankenmonster自定义权限,在我看来,在Django框架方面并不是很习惯。因此,我提出了以下解决方案-它@list_route
与@detail_route
装饰器的工作方式非常相似。我们依靠这样的事实,即方法/函数是一流的对象
首先,我要创建这样的装饰器:
decorators.py
def route_action_arguments(**kwargs):
"""
Add arguments to the action method
"""
def decorator(func):
func.route_action_kwargs = kwargs
return func
return decorator
Run Code Online (Sandbox Code Playgroud)
如您所见,它向其函数添加了一个字典,该字典使用作为arg列表传递的参数进行装饰
现在,我创建了这样的mixin: mixins.py
class RouteActionArgumentsMixin (object):
"""
Use action specific parameters to
provide:
- serializer
- permissions
"""
def _get_kwargs(self):
action = getattr(self, 'action')
if not action:
raise AttributeError
print('getting route kwargs for action:' + action)
action_method = getattr(self, action)
kwargs = getattr(action_method, 'route_action_kwargs')
print(dir(kwargs))
return kwargs
def get_serializer_class(self):
try:
kwargs = self._get_kwargs()
return kwargs['serializer']
except (KeyError, AttributeError):
return super(RouteActionArgumentsMixin, self).get_serializer_class()
def get_permissions(self):
try:
kwargs = self._get_kwargs()
return kwargs['permission_classes']
except (KeyError, AttributeError):
return super(RouteActionArgumentsMixin, self).get_permissions()
Run Code Online (Sandbox Code Playgroud)
Mixin做两件事;get_permissions
调用when时,它将检查执行了哪个“动作”,并从route_action_kwargs
与viewset.action_method.route_action_kwargs
当get_serializer_class
被调用时,它执行相同的操作并serializer
从中选择route_action_kwargs
现在我们可以使用它的方式:
@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
"""
User and profile managment viewset
"""
queryset = User.objects.all()
serializer_class = UserSerializer
@list_route(methods=['post'])
@route_action_arguments(permission_classes=(AllowAny,), serializer=LoginSerializer)
def login(self, request):
serializer = self.get_serializer_class()(data=request.data)
Run Code Online (Sandbox Code Playgroud)
对于自定义路由,我们可以显式定义,只需@route_action_arguments
在方法上显式设置即可。
在通用视图集和方法方面,我们仍然可以使用
@method_decorator
@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
19364 次 |
最近记录: |