man*_*ari 0 python django django-models django-views django-rest-framework
场景:我有组和权限,权限与组关联,并且该组与用户关联。现在我尝试通过DjangoModelPermissions实现视图的权限
这对于实现查询集的以下代码行效果很好;
class UpdateCampaignView(generics.UpdateAPIView):
authentication_classes = [TokenAuthentication]
permission_classes = [DjangoModelPermissions]
queryset = Campaign.objects.all()
serializer_class = UpdateCampaignSerializer
def get_object(self):
campaign_id = self.request.data.get("id")
return Campaign.objects.get(id =campaign_id)
Run Code Online (Sandbox Code Playgroud)
但我想将其实现为基于类的 APIView,无需使用 queryset 关键字,如下所示:
class RetrieveCampaignView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [DjangoModelPermissions] #this is what i want to do
def get(self, request, *args, **kwargs):
try:
campaign = Campaign.objects.get(id = request.data.get("id"))
searializer = GetCampaignSerializer(campaign)
return Response({"status":True , "payload":searializer.data})
except:
return Response({"status":False}, status=status.HTTP_404_NOT_FOUND)
Run Code Online (Sandbox Code Playgroud)
但这给出了以下错误:
djangorest框架错误无法在未设置.queryset或没有.get_queryset()方法的视图上应用DjangoModelPermissions
课堂上有讲解DjangoModelPermissions;
\n\n此权限只能应用于提供
\n.queryset属性的视图类。 \n
因此,您不能在没有queryset属性的情况下使用此权限类。您可以创建自己的权限类以与 一起使用,而不是使用它APIView。例如你有permissions.py喜欢;
from rest_framework.permissions import BasePermission\n\n\nclass MyPermission(BasePermission):\n message = "You do not have permission to retrive object"\n\n def has_permission(self, request, view):\n if request.user.has_perm("app.view_yourmodel"):\n return True\n return False\nRun Code Online (Sandbox Code Playgroud)\n并将此自定义权限类指定给您的视图;
\nfrom rest_framework.permissions import IsAuthenticated\n\nfrom app.permissions import MyPermission\n\n\nclass RetrieveCampaignView(APIView):\n authentication_classes = [TokenAuthentication]\n permission_classes = [IsAuthenticated, MyPermission]\n\n ...\nRun Code Online (Sandbox Code Playgroud)\n最后,你应该从 django 模型中找到你自己的权限代码Permission,并将其更改为app.view_yourmodel. 来自文档;
\n\n当 django.contrib.auth 在 INSTALLED_APPS 设置中列出时,它将确保为以下之一中定义的每个 Django 模型创建四个默认权限 \xe2\x80\x93 添加、更改、删除和查看 \xe2\x80\x93您安装的应用程序。
\n
所以,如果你想找到你的模型权限;
\nfrom django.contrib.auth.models import Permission\nfrom django.contrib.contenttypes.models import ContentType\n\nfrom app.models import Campaign\n\n\ncontent_type = ContentType.objects.get_for_model(Campaign)\nperms = Permission.objects.filter(content_type=content_type)\nprint([perm.codename for perm in perms])\nRun Code Online (Sandbox Code Playgroud)\n您可以访问文档以获取有关自定义权限的更多信息。
\n\n\n如何使 ==> request.user.has_perm(\'app.view_yourmodel\') 动态\nfor code_name 否则我需要为每个 has_perm 参数(即 code_name)传递一大堆 MyPermission for\n每个视图。
\n
如果您想使用更通用的自定义权限结构,那么您可以实现自己的逻辑。例如,让我们创建自己的视图属性,perm_slug = "app.model_name"因为我们需要知道用户尝试执行操作的模型。您必须为要使用的所有视图正确实现此属性MyPermission,然后在权限类中解析此属性,获取相关的权限密钥并检查请求用户是否具有此权限密钥。
class MyPermission(BasePermission):\n message = "You do not have permission to perform action"\n permission_map = {\n "GET": "{app_label}.view_{model_name}",\n "POST": "{app_label}.add_{model_name}",\n "PUT": "{app_label}.change_{model_name}",\n "PATCH": "{app_label}.change_{model_name}",\n "DELETE": "{app_label}.delete_{model_name}",\n }\n\n def _get_permission(self, method, perm_slug):\n app, model = perm_slug.split(".")\n if method not in self.permission_map:\n raise MethodNotAllowed(method)\n perm = self.permission_map.get(method).format(app_label=app, model_name=model)\n return perm\n\n def has_permission(self, request, view):\n perm = self._get_permission(\n method=request.method, perm_slug=view.perm_slug\n )\n if request.user.has_perm(perm):\n return True\n return False\nRun Code Online (Sandbox Code Playgroud)\n并修改您的视图,例如;
\nclass RetrieveCampaignView(APIView):\n authentication_classes = [TokenAuthentication]\n permission_classes = [IsAuthenticated, MyPermission]\n perm_slug = "app.campaign"\n\n ...\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1421 次 |
| 最近记录: |