6

不可见的,我为了每个对象的权限管理使用django-guardian分配权限。对象与Django的监护人管理

对于一个给定用户本人允许的所有权限一个对象:

joe = User.objects.get(username="joe") 

mytask = Task.objects.get(pk=1) 

assign('add_task', joe, mytask) 
assign('change_task', joe, mytask) 
assign('delete_task', joe, mytask) 

,我得到的,如预期:

In [57]: joe.has_perm("add_task", mytask) 
Out[57]: True 

In [58]: joe.has_perm("change_task", mytask) 
Out[58]: True 

In [59]: joe.has_perm("delete_task", mytask) 
Out[59]: True 

在admin.py我也会让TaskAdmin从GuardedModelAdmin而不是继承admin.ModelAdmin

现在,当我连接到我的网站与乔,在管理员我得到:

You don't have permission to edit anything 

我不是应该能够编辑对象mytask?

我必须使用内置的基于模型的权限系统设置一些权限?

我错过了什么?

编辑

我尝试添加选项user_can_access_owned_objects_only,这是为了对付我的问题,但我仍然看不到任何东西在我的管理...

class TaskAdmin(GuardedModelAdmin): 

    user_can_access_owned_objects_only = True 

    pass 

admin.site.register(Task, TaskAdmin) 

谢谢你

回答

3

为了只看到当前用户拥有的实例,我给他所有权限

add_task=Permission.objects.get(codename="add_task") 
change_task=Permission.objects.get(codename="change_task") 
delete_task=Permission.objects.get(codename="delete_task") 

joe.user_permissions.add(add_task) 
joe.user_permissions.add(change_task) 
joe.user_permissions.add(delete_task) 

然后我设置少数情况下,允许使用guardian.shortcuts.assign,我筛选查询集在admin:

class TaskAdmin(admin.ModelAdmin): 

    def queryset(self, request): 
      if request.user.is_superuser: 
       return super(TaskAdmin, self).queryset(request) 
      return get_objects_for_user(user=request.user, perms=['add_task', 'change_task', 'delete_task'], klass=Task) 

它远非完美,但我找不到任何其他的解决办法。

2

Django管理,特别是它在处理瓦特/ change许可,有点粗粒度。内部方法ModelAdmin.has_change_permission()涵盖实际上缺少的view权限的检查。

其次,GuardedModelAdmin带来了所有权检查(通过user_can_access_owned_objects_only)和管理行级权限的表单。它没有向Django Admin提供任何其他行级访问策略。

对于Django管理典型的行级权限的场景,我想建议的代码,在这里我介绍了一个可选的“查看”的权限:

class ExtendedGuardedModelAdmin(GuardedModelAdmin): 
    def queryset(self, request): 
     qs = super(ExtendedGuardedModelAdmin, self).queryset(request) 
     # Check global permission 
     if super(ExtendedGuardedModelAdmin, self).has_change_permission(request) \ 
      or (not self.list_editable and self.has_view_permission(request)): 
       return qs 
     # No global, filter by row-level permissions. also use view permission if the changelist is not editable 
     if self.list_editable: 
      return get_objects_for_user(request.user, [self.opts.get_change_permission()], qs) 
     else: 
      return get_objects_for_user(request.user, [self.opts.get_change_permission(), self.get_view_permission(
)], qs, any_perm=True) 

    def has_change_permission(self, request, obj=None): 
     if super(ExtendedGuardedModelAdmin, self).has_change_permission(request, obj): 
      return True 
     if obj is None: 
      # Here check global 'view' permission or if there is any changeable items 
      return self.has_view_permission(request) or self.queryset(request).exists() 
     else: 
      # Row-level checking 
      return request.user.has_perm(self.opts.get_change_permission(), obj) 

    def get_view_permission(self): 
     return 'view_%s' % self.opts.object_name.lower() 

    def has_view_permission(self, request, obj=None): 
     return request.user.has_perm(self.opts.app_label + '.' + self.get_view_permission(), obj) 

    def has_delete_permission(self, request, obj=None): 
     return super(ExtendedGuardedModelAdmin, self).has_delete_permission(request, obj) \ 
       or (obj is not None and request.user.has_perm(self.opts.get_delete_permission(), obj)) 

通过这种方式,你可以实现更灵活的权限检查,用户权限现在是全球性的,用户OBJ-权限基于行级:

  • joe.user_permissions.add(add_task)
    乔添加新的任务(没有行级“加”许可)
  • joe.user_permissions.add(change_task)
    乔可以改变所有的任务
  • joe.user_permissions.add(delete_task)
    乔可以删除所有的任务
  • assign(Task._meta.get_change_permission(), joe, obj)
    乔更改任务OBJ,看到包含变更列表的OBJ以及其他变化的任务。
  • assign(Task._meta.get_delete_permission(), joe, obj)
    乔删除任务OBJ
  • assign('view_task', joe, obj)
    [可选]乔查看任务OBJ(你可能想在定制的管理视图页,以检查此权限)
  • joe.user_permissions.add(Permission.objects.get(codename='view_task', ...))
    [可选] joe可以查看更改列表中的所有任务,只要更改列表不可内联编辑。如果joe可以从没有更改权限的raw_id_fields中拾取项目,这很有用。
  • ...

你可以忽略“查看”的权限安全,如果它是你没用。

目前,django.contrib.admin.util.get_deleted_objects不许可的检查过程中兑现obj的,如果你需要在删除检查行级权限,通过修改if not user.has_perm(p):线if not user.has_perm(p, obj):修补get_deleted_objects。相对门票13539 & 16862

+0

你应该通过在self.has_view_permission – Don

+0

@Don是的“请求”,而不是“request.user”,感谢指出=) – okm

+0

可能是版本变化相关的问题,但运行到'选项'对象没有属性'get_change_permission' – Mutant