发布时间:2019/09/02 12:58:03   更新时间:2020/07/31 19:50:01
参考官网:https://django-guardian.readthedocs.io/
为什么要使用django-guardian?就是说,默认的django对权限的控制,是能到model(数据库表)级别,如果要对object(数据库表的一条记录)也进行权限控制,就要用到django-guardian。
事实上,我们不少需求都要用到这个东西。
drf如果要用对象级权限控制,也要用这个东东。
django-guardian实现了对象级权限控制,还和django的modle、DTL、drf、cmd等结合的很好。
pip install django-guardian
安装后
python manage.py migrate
同步数据库表表:
执行完以后,会创建匿名用户,可以在admin用户里边看到。
Guardian匿名用户与Django匿名用户不同。Django匿名用户在数据库中没有条目,但是Guardian匿名用户也有。
在数据库里,还会出现guardian权限的表:
guardian_groupobjectpermission
guardian_userobjectpermission
guardian.shortcuts.assign(perm, user_or_group, obj=None),这个方法接受3个参数:
perm,这个参数是一个字符串,代表一个许可,格式必须为<app>.<perm_codename>或者<perm_codename>。但是如果第三个参数是None,则必须为<app>.<perm_codename>格式。因此建议还是统一使用<app>.<perm_codename>格式。
注意:app并不是app的全路径,而是最后一级的模块名。这一点和INSTALL_APP中的app全路径不同,如果你的app module不只一级的话,这地方一定要注意。
user_or_group,这个参数是一个User或者Group类型的对象。
obj,这个参数就是相关的对象了。改参数是可省略的,如果省略则赋予Model权限。
注意:codename一般用默认的,是auth_permission表里边的codename列。
示例代码:
from guardian.shortcuts import assign
user = User.objects.create(username='liuyong')
assign('app.view_task', user)
【分配model权限】
【一旦赋予模型级的权限,那么所有该模型的对象级别的权限就都有了,所以应该先从对象级别进行设置】
user.has_perm('app.view_task') >>True
【判断是否有mode权限】
user = User.objects.get(username='liuyong')
user.user_permissions.clear()
【清理权限】
task = Task.objects.create(summary='Some job', content='')
assign('app.view_task', user, task)
【分配obj权限】
user = User.objects.get(username='liuyong')#刷新缓存
user.has_perm('app.view_task',task)
>>True
【判断是否有obj权限】
user.has_perm('app.view_task')#模型级别的权限还没有
>>False
【判断是否有mode权限】
>>> group = Group.objects.create(name='employees')
>>> assign('change_task', group, task)
【给组附加权限】
>>> user.has_perm('change_task', task)
False
>>> # user还不是employees组的成员,我们加入一下
>>> user.groups.add(group)
【添加组】
>>> user.has_perm('change_task', task)
True
guardian.shortcuts.remove_perm(perm,user_or_group=None, obj=None)
样例代码:
>>> from guardian.shortcuts import remove_perm
>>> remove_perm('change_site', user, site)
>>> user = User.objects.get(username='joe') #刷新user对象缓存
>>> joe.has_perm('change_site', site)
False
guardian.shortcuts.get_perms(user_or_group,obj)
该方法返回user对象对obj对象所有的权限。这个行数接受两个参数,一个是user对象或者组对象,一个是相关的对象。
'permcodename' in get_perms(group,obj)来判断该组是否有这个权限,因为group没有has_perm方法。
guardian.shortcuts.get_objects_for_user(user, perms, klass=None, use_groups=True, any_perm=False)
该函数获得该用户下指定perm列表中的所有对象。比如我要获得某一个用户,拥有编辑权限的所有帖子。
get_objects_for_user(user,'app.change_post')
>>所有可编辑的帖子
https://blog.csdn.net/scdxmoe/article/details/72678005
1、在admin添加对象权限。
2、在admin登录的用户显示对象权限。
#下边部分的增加,用来在admin页面中显示guarded的权限控制。
# app是否在主页面中显示的话由该函数决定
def has_module_permission(self, request):
if super().has_module_permission(request):
return True
return self.get_model_objs(request).exists()
# 在显示数据列表额时候,哪些数据显示,哪些不显示,由该函数控制
def get_queryset(self, request):
if request.user.is_superuser:
return super().get_queryset(request)
data = self.get_model_objs(request)
return data
# 内部用来获取某个用户有权限访问的数据行
def get_model_objs(self, request, action=None, klass=None):
opts = self.opts
actions = [action] if action else ['view', 'change', 'delete']
klass = klass if klass else opts.model
model_name = klass._meta.model_name
return get_objects_for_user(user=request.user, perms=[f'{perm}_{model_name}' for perm in actions],
klass=klass, any_perm=True)
# 用来判断某个用户是否有某个数据行的权限
def has_perm(self, request, obj, action):
opts = self.opts
codename = f'{action}_{opts.model_name}'
if obj:
return request.user.has_perm(f'{opts.app_label}.{codename}', obj)
else:
return self.get_model_objs(request, action).exists()
# 是否有查看某个数据行的权限
def has_view_permission(self, request, obj=None):
return self.has_perm(request, obj, 'view')
# 是否有修改某个数据行的权限
def has_change_permission(self, request, obj=None):
return self.has_perm(request, obj, 'change')
# 是否有删除某个数据行的权限
def has_delete_permission(self, request, obj=None):
return self.has_perm(request, obj, 'delete')
# 用户应该拥有他新增的数据行的所有权限
def save_model(self, request, obj, form, change):
result = super().save_model(request, obj, form, change)
if not request.user.is_superuser and not change:
opts = self.opts
actions = ['view', 'add', 'change', 'delete']
[assign_perm(f'{opts.app_label}.{action}_{opts.model_name}', request.user, obj) for action in actions]
return result
比如blog的model被改造后,
用admin登录admin页面,
选择某条blog以后,再右上角的历史记录旁边,有对象权限,进行修改。
添加权限会出现在表:guardian_userobjectpermission
注意,授权创建文章,guardian_userobjectpermission表会自动出现权限。
删除文章后,这个不会自动删除。
文章分类的外键会删除。
如果加上对象级权限,又对对象进行了删除,就要用下边命令清理。
django命令:要在env中敲命令。
在env外的命令是:
/home/your_root_path/…/env/bin/python3 /home/your_root_path/… /manage.py clean_orphan_obj_perms