跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Django怎么实现基于角色的权限_Python利用Group与Permission控制访问

给用户分配角色需显式调用user.groups.add(group_instance);权限绑定须运行makemigrations生成自定义权限,再通过group.permissions.add(perm)添加;@permission_required失效主因是权限字符串错误或用户未加入对应组。 怎么给用户分配角色(Group) Group 是 Django 权限体系里最轻量、也最常用的角色抽象,它不强制你写模型或继承类,直接复用内置的
Group
模型就行。关键不是“建多少组”,而是“谁在什么场景下改组”——比如后台管理员手动加,注册时自动进默认组,或者通过 API 动态同步。 常见错误是把权限直接塞进 Group 之后就不管了,结果用户登录后
request.user.has_perm('blog.delete_post')
还是返回
False
:忘了用户得显式加入该 Group。 添加用户到组:
user.groups.add(group_instance)
或
user.groups.add(123)
(传 ID 也行) 从组移除:
user.groups.remove(group_instance)
清空所有组:
user.groups.clear()
(注意:这不会删权限,只清组关联) 检查是否在某组:
user.groups.filter(name='editor').exists()
,比
in
更可靠(避免缓存/延迟问题) Permission 怎么绑定到模型和视图 Django 的
Permission
默认随每个模型自动生成
add_
、
change_
、
delete_
、
view_
四种,但仅当模型定义了
Meta.permissions
才能扩展自定义项,比如
('publish_post', 'Can publish post')
。 容易踩的坑是:写了
Meta.permissions
却没跑
python manage.py makemigrations
—— 自定义权限根本不会进数据库,
Group.permissions.add()
会静默失败或报
Permission matching query does not exist
。 立即学习 “ Python免费学习笔记(深入) ”; 查权限对象:
from django.contrib.auth.models import Permission; perm = Permission.objects.get(codename='publish_post')
加权限到组:
group.permissions.add(perm)
视图中判断:
if request.user.has_perm('blog.publish_post'):
(注意 app_label.codename 格式) 模板中用:
{% if perms.blog.publish_post %}...{% endif %}
(需确保
context_processors.auth
已启用) 为什么 @permission_required 有时不生效
@permission_required
看似简单,但失效往往不是装饰器写错了,而是路径或参数没对齐。它默认重定向到
settings.LOGIN_URL
,如果用户已登录却跳转登录页,大概率是权限字符串写错,或者用户根本没被赋予对应权限(包括没加 Group、没同步权限、拼写大小写不一致)。 Python 3.14.3 微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。 下载 另一个隐蔽问题是:它只检查权限,不检查用户是否活跃(
is_active=False
)或是否为 staff(
is_staff=False
在 admin 视图里会额外拦截)。 正确写法:
@permission_required('blog.change_post', raise_exception=True)
(加
raise_exception=True
可避免静默重定向) 函数视图中手动检查:
if not request.user.has_perm('blog.change_post'): raise PermissionDenied
Class-Based View 推荐用
UserPassesTestMixin
或
PermissionRequiredMixin
,后者要求设置
permission_required = 'blog.change_post'
别用
@login_required
替代权限检查——登录 ≠ 有权限 Group 和 Permission 的性能与边界在哪 单次请求里查权限本身开销极小(Django 会缓存
user.get_all_permissions()
结果),真正拖慢的是频繁调用
user.has_perm()
并传入不同 app_label 或动态 codename——比如循环里判断每个文章的编辑权限,就会触发多次 DB 查询。 更麻烦的是跨模型权限(如“能编辑自己发布的文章”)无法靠内置 Group+Permission 解决,必须手写逻辑,这时硬套
Permission
反而让权限散落在 view、model、template 多处,难维护。 批量查权限建议预加载:
user = User.objects.prefetch_related('groups__permissions').get(id=xxx)
复杂规则(如对象级权限)别强扭内置机制,考虑
django-guardian
或自定义
has_object_permission
Group 不支持嵌套,想做“编辑组继承内容组权限”?得手动同步,或换用
django-role-permissions
这类第三方包 生产环境别用
is_superuser=True
当权限兜底——它绕过所有权限检查,审计和最小权限原则全失效 权限不是越细越好,关键是哪些操作真需要隔离。比如“删除用户”和“导出报表”权限混在一个 Group 里,后期拆分就会牵连大量已有代码。一开始就把权限 codename 命名清楚、范围划明白,比后期补迁移靠谱得多。

相关文章