Django 权限管理和guardian插件

内置权限管理

Django内置的权限管理, 是一种表权限, 就是可分别配置某管理员用户对某个表的全部数据有没有增删改查4种权限.

图形界面配置权限

之前提到,使用命令行创建超管用户:

python manage.py createsuperuser

这其实是在最普通的用户的基础上将is_superuseris_staffis_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代表以什么字符开头. 所以以上代码可给刚刚创建的用户赋予“查看”和“删除”所有模型表内所有对象的权限.

guardian插件

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的
) 

在admin.py中引入

使用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

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django提供了内置的用户认证和权限管理功能,可以方便地实现用户注册、登录、注销以及不同用户角色的权限管理。下面是一些常用的Django用户认证和权限管理的功能和方法: 1. 用户注册: - 创建一个注册视图函数,接收用户提交的注册信息,并进行表单验证。 - 使用Django的内置User模型创建用户,并保存到数据库中。 2. 用户登录: - 创建一个登录视图函数,接收用户提交的登录信息,并进行表单验证。 - 使用Django的`authenticate()`函数验证用户的用户名和密码是否匹配。 - 使用Django的`login()`函数将用户登录状态保存到会话中。 3. 用户注销: - 创建一个注销视图函数,调用Django的`logout()`函数注销当前用户。 4. 访问控制: - 使用Django的`@login_required`装饰器,限制只有登录用户才能访问特定页面或执行特定操作。 - 使用Django的`@permission_required`装饰器,限制只有具备特定权限的用户才能访问。 5. 用户角色和权限管理: - 使用Django的内置Group模型,创建不同的用户组或角色。 - 将用户添加到相应的用户组中,实现不同权限的分配。 - 使用Django的`@group_required`装饰器,限制只有属于特定用户组的用户才能访问。 6. 自定义权限: - 使用Django的内置Permission模型,创建自定义的权限。 - 将权限分配给用户组或用户。 7. 表单验证: - 使用Django的内置表单验证功能,确保用户输入的数据符合要求。 8. 记住登录状态: - 使用Django的`SESSION_COOKIE_AGE`设置会话cookie的过期时间,以保持用户的登录状态。 以上是一些常用的Django用户认证和权限管理的功能和方法。通过使用这些功能和方法,可以轻松实现用户认证和权限管理的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值