【问题标题】:django-guardian and django-rest-frameworkdjango-guardian 和 django-rest-framework
【发布时间】:2016-09-06 17:23:43
【问题描述】:

我想在一个 restful 项目中使用 django-guardian 管理我的对象权限(使用 django-rest-framework)。

我想要什么:

  • 仅当连接的用户拥有 “add_modelname”权限。
  • 连接用户创建对象时,设置“delete_modelname” 和“change_modelname”权限。
  • 仅当连接的用户拥有 “change_modelobject”权限。
  • 仅当连接的用户拥有 “delete_modelobject”权限。

我正在尝试使用此代码管理这些案例:

view.py

class ModelNameViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.

    Additionally we also provide an extra `highlight` action.
    """
    queryset = ModelName.objects.all()
    serializer_class = ModelNameSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, ModelNamePermission)

    def create(self, request, *args, **kwargs):
        assign_perm("change_modelname", request.user, self)
        assign_perm("delete_modelname", request.user, self)
        return super().create(request, *args, **kwargs)

permissions.py

class ModelNamePermission(permissions.BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """

    def has_permission(self, request, view):
        if request.method in ['GET']:
            return request.user.has_perm('view_modelname')        
        if request.method in ['POST']:
            return request.user.has_perm('add_modelname')
        if request.method in ['PUT', 'PATCH']:
            return request.user.has_perm('change_modelname')
        if request.method in ['DELETE']:
            return request.user.has_perm('delete_modelname')
        return False

    def has_object_permission(self, request, view, obj):         
        if request.method in ['GET']:
            return request.user.has_perm('view_modelname', obj)        
        if request.method in ['POST']:
            return request.user.has_perm('add_modelname', obj)
        if request.method in ['PUT', 'PATCH']:
            return request.user.has_perm('change_modelname', obj)
        if request.method in ['DELETE']:
            return request.user.has_perm('delete_modelname', obj)
        return False

我遇到的第一个问题是这行有错误:

assign_perm("change_modelname", request.user, self)

错误:

error: 'ModelNameViewSet' object has no attribute '_meta'

而且我认为其余代码将无法正常工作,但至少您可以看到我想要做什么。

我还没有看到任何关于这些具体案例的例子。

编辑: 另一件事是这段代码:

request.user.has_perm('view_coachingrequest')

总是返回真。但我从来没有给我的用户设置这个权限(只用管理员用户试过,也许这就是原因)。

【问题讨论】:

  • 我想做同样的事情。你做到了吗?

标签: permissions django-rest-framework django-guardian


【解决方案1】:

视图集的create 方法将返回一个新创建的模型实例。您正在尝试将权限分配给视图集对象本身。 create 方法的代码应如下所示:

def create(self, request, *args, **kwargs):
    instance = super().create(request, *args, **kwargs)
    assign_perm("change_modelname", request.user, instance)
    assign_perm("delete_modelname", request.user, instance)
    return instance

这将创建模型实例,然后在返回之前为其分配所需的权限。

【讨论】:

  • DRF 视图集中的 create 方法返回一个响应对象,而不是模型的实例。这里的代码:github.com/encode/django-rest-framework/blob/… 你在考虑序列化器中的 create 方法吗?
  • 实际上它可以在序列化程序或视图集的 perform_create() 方法中完成(后者由此处的答案显示:stackoverflow.com/questions/41230236/…)。因此,您可以选择将代码保存在哪里。对我来说,我想我会在序列化程序中执行此操作(这可能允许您编写更清晰的错误处理代码,将对象创建与权限分配在同一位置)
猜你喜欢
  • 2019-05-12
  • 1970-01-01
  • 2016-10-21
  • 2021-09-09
  • 2017-05-26
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 1970-01-01
相关资源
最近更新 更多