Django内置的权限管理, 是一种表权限, 就是可分别配置某管理员用户对某个表的全部数据有没有增删改查4种权限.
之前提到,使用命令行创建超管用户:
python manage.py createsuperuser
这其实是在最普通的用户的基础上将is_superuser
、is_staff
和is_active
三个属性设为True,在管理界面的首页 › 认证和授权 › 用户
可找到用户详情页,会发现超管用户的权限属性如下:
Image
并且在用户权限中,超管用户拥有所有可设置的权限(所有模型表的增删改查)。
首页 › 认证和授权 › 用户
中可添加用户,并且可以用图形界面配置新用户的权限,以及权限组都可以用图形界面。
Image
用代码可以自动、批量创建用户。可以用django-shell, 也可写入文件。 以django-shell为例, 先在项目目录运行django-shell:python manage.py shell
, 然后运行:
from django.contrib.auth.models import User
from django.contrib.auth.models import Permission
user = User.objects.create_user( username='jam123', password='12345678', is_staff=True, first_name='jam')
以上代码可创建一个管理员用户, 可以登录后台, 但目前还无任何权限. 权限本身就是多对多关联对象, 配置方法与多对多关联关系一样:
from django.db.models.query_utils import Q
user.user_permissions.add( *Permission.objects.filter( Q(codename__startswith='view')| Q(codename__startswith='delete')))
codename一般写为以add、change、delete、view
开头,后接下划线加表名小写,例如add_user
,__startswith
代表以什么字符开头. 所以以上代码可给刚刚创建的用户赋予“查看”和“删除”所有模型表内所有对象的权限.
Django框架的一大特色就是有各种各样强大的插件可以选用。 内置的权限管理只能配置表权限,如果要达到“某个管理员控制某个单独对象”的功能,需要安装使用guardian插件。
在有pip的前提下,在项目目录下执行:
pip install django-guardian
安装好后,需要在项目settings.py文件中指定app,在INSTALLED_APPS
中这样添加:
INSTALLED_APPS = [
'guardian',
]
AUTHENTICATION_BACKENDS
是指定可以进行权限控制的工具,在其中这样添加:
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend', # 这是Django自带默认的
'guardian.backends.ObjectPermissionBackend', # 这是guardian的
)
使用Guardian最直观的特色就是在django-admin页面可以图形化地使用对象权限功能。 首先,在admin.py开头,从guardian添加两个导入:
from guardian.admin import GuardedModelAdminMixin
from guardian.shortcuts import get_objects_for_user, assign_perm
GuardedModelAdminMixin
是一个类,包含权限管理的功能,其中Mixin(混入)代表这个类不能单独作为ModelAdmin类使用,需要与其他的ModelAdmin类共同作为子类的父类,新的子类即可既有ModelAdmin的功能也有Guardian权限管理的功能。 但是,GuardedModelAdminMixin
本身的功能还是欠缺了点,或者说它本来就是希望开发者自定义重写的。网上有大神将此类继承后重写,完善了其功能,我们将代码抄过来即可(可根据自己项目的特点修改其代码):
class GuardedMixin(GuardedModelAdminMixin):
# app是否在主页面中显示,由该函数决定
def has_module_permission(self, request):
if super().has_module_permission(request):
return True
return self.get_model_objs(request,'view').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
data = get_objects_for_user(
user=request.user,
perms=[f'{perm}_{model_name}' for perm in actions],
klass=klass, any_perm=True
)
if hasattr(request.user, 'teacher'):
data = teacher.objects.filter(id=request.user.teacher.id) | data
return data
# 用来判断某个用户是否有某个数据行的权限
def has_perm(self, request, obj, action):
opts = self.opts
codename = f'{action}_{opts.model_name}'
if hasattr(request.user, 'teacher') and obj == request.user.teacher:
return True
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
当然,这些代码不是尽善尽美的,我们可根据自己项目的特点适当修改这些代码。 而后,将这个我们自己写的GuardedMixin
类作为我们自己原来的模型的ModelAdmin
类的父类之一:
class TeacherAdmin(GuardedMixin,ModelAdmin):
# 详情表单页
inlines = [Class_head_yearInline,FamilyMemberInline]
fieldsets = [
# ...
admin.py
就编辑完成了,在admin管理页面的Teacher页面中就可以设置某个管理员针对某个teacher对象的权限了。
用超级管理员账户,打开某位教师的信息详情页,在右上角出现的“对象权限”按钮,就是我们配置的guardian插件体现的效果。
Image
点击它。
Image
用户身份写入管理员的名字,点击管理用户,便可设置此管理员针对此对象的权限设置,共有增删改查四种设置。
Image