django自带权限系统不够用,因其仅支持静态模型级权限(如add_user),无法满足企业级rbac所需的动态角色分配、数据级控制(如“仅编辑自己订单”)、组织架构继承及多租户场景;硬套group会导致角色膨胀、耦合严重,且缺乏上下文感知能力。

为什么 Django 自带的权限系统不够用?
Django 的 auth.Permission 和 User.has_perm() 适合简单 CRUD 权限,但企业级 RBAC 要求角色可动态分配、权限可细粒度绑定到具体数据(如“只能编辑自己创建的订单”)、支持多租户或组织架构继承——这些 Django 默认不提供。硬套 Group 模型会导致角色膨胀、权限耦合严重,且无法表达“部门管理员可管理本部门用户”这类上下文感知逻辑。
如何扩展 User 和 Permission 模型以支持角色继承与数据范围?
不要修改 auth.User,而是通过一对一关系扩展;权限控制不能只靠 codename 字符串,需引入显式的数据范围字段。关键点:
- 新建
Role模型,含name、org_unit(外键到部门/租户)、is_active - 建立
RolePermission中间表,关联Role和ContentType+codename,并加scope字段(如"self"、"department"、"all") - 为
User添加roles = models.ManyToManyField(Role),支持一人多角色 - 避免重写
has_perm,改用自定义方法user.can_do("change_order", order),内部根据order.owner或order.department动态判断scope
如何在视图和 API 中统一拦截无权限访问?
Django 的 @permission_required 只校验静态 codename,无法处理数据级权限。推荐用基于类的权限检查:
- 写一个
ObjectPermissionMixin,重载dispatch(),调用self.request.user.can_do(self.permission_required, self.get_object()) - DRF 中用自定义
BasePermission子类,在has_object_permission()里做同样判断,注意区分SAFE_METHODS和写操作 - 务必在
get_queryset()层过滤数据(如Order.objects.filter(department=request.user.department)),否则仅靠对象级检查可能被绕过 - 错误响应统一返回
403,不暴露“对象不存在”还是“无权限”,防止信息泄露
为什么缓存 Role-Permission 关系比实时查库更关键?
每次请求都 JOIN Role→RolePermission→ContentType 会拖慢接口,尤其当用户有多个角色、权限项超过 50 条时。实操建议:
- 用
cache.set(f"user_role_perms_{user.id}", perms_list, 300)缓存扁平化权限列表(如[("view_order", "self"), ("change_order", "department")]) - 在
Role.save()、User.roles.add()等变更点主动cache.delete(f"user_role_perms_{user.id}") - 不要缓存原始 QuerySet,缓存解析后的元组结构,避免 ORM 实例序列化开销
- 生产环境必须设置缓存失效策略,否则角色调整后权限延迟生效
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











