Django用户权限管控:非超级用户的分组管理员需求实现
解决Django Admin中角色A的权限限制问题
我刚好在项目里处理过几乎一模一样的多角色权限场景,给你一套最简的原生Django实现方案,不用额外装第三方库,核心是通过自定义ModelAdmin的几个钩子来锁死权限边界:
1. 锁定User模型的敏感操作
首先要杜绝角色A修改is_superuser这类敏感权限,同时限制他们只能看到同D值的用户。我们重写默认的UserAdmin:
from django.contrib import admin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from .models import User class CustomUserAdmin(BaseUserAdmin): # 控制不同角色能看到的字段组 def get_fieldsets(self, request, obj=None): fieldsets = super().get_fieldsets(request, obj) # 当前用户是角色A且不是超级用户时,隐藏超级用户权限字段 if request.user.is_appadmin and not request.user.is_superuser: # 移除包含is_superuser的字段组(默认在"Permissions"分组里) fieldsets = [ (name, opts) for name, opts in fieldsets if 'is_superuser' not in opts.get('fields', []) ] # 只允许角色A修改B、C类角色的标识字段 fieldsets.append(("用户角色", {"fields": ("is_appuser", "is_someuser")})) return fieldsets # 限制角色A只能查看同D值的用户 def get_queryset(self, request): qs = super().get_queryset(request) if request.user.is_appadmin and not request.user.is_superuser: # 替换成你实际的User与D模型的多对多关联字段(比如user.ds) return qs.filter(d__in=request.user.d_set.all()) return qs # 强制控制角色A创建用户的权限 def save_model(self, request, obj, form, change): if request.user.is_appadmin and not request.user.is_superuser: # 彻底锁死超级用户权限,无论表单提交什么都设为False obj.is_superuser = False # 如果创建的是C类用户,自动赋予后台访问权限(假设用is_staff字段) if obj.is_someuser: obj.is_staff = True # 自动关联当前角色A的D值给新创建的用户 obj.d_set.set(request.user.d_set.all()) super().save_model(request, obj, form, change)
2. 限制分组的多对多操作权限
接下来处理角色A只能将同D值的C类用户添加到同D值分组的需求,重写GroupAdmin:
from django.contrib.auth.models import Group class CustomGroupAdmin(admin.ModelAdmin): # 控制分组选择用户时的可选范围 def formfield_for_manytomany(self, db_field, request, **kwargs): if db_field.name == "user_set" and request.user.is_appadmin and not request.user.is_superuser: # 只显示同D值的C类用户 kwargs["queryset"] = User.objects.filter( is_someuser=True, d__in=request.user.d_set.all() ) return super().formfield_for_manytomany(db_field, request, **kwargs) # 限制角色A只能查看同D值的分组 def get_queryset(self, request): qs = super().get_queryset(request) if request.user.is_appadmin and not request.user.is_superuser: return qs.filter(d__in=request.user.d_set.all()) return qs
3. 注册自定义Admin并分配基础权限
最后替换默认的Admin注册:
# 先注销默认的User和Group Admin admin.site.unregister(User) admin.site.register(User, CustomUserAdmin) admin.site.unregister(Group) admin.site.register(Group, CustomGroupAdmin)
然后在Django后台的权限管理里,给角色A对应的用户组分配以下权限:
- 用户模型的添加、更改、删除权限
- 分组模型的更改权限
- 后台访问权限(确保角色A用户的
is_staff字段为True)
关键注意点
- 代码里的
d_set要替换成你实际项目中User与D模型的多对多关联字段名(比如如果关联字段是ds,就改成ds.all()) - 如果你的后台访问权限不是用
is_staff,替换成你项目里对应的字段即可 - 这套方案完全用Django原生功能实现,没有额外依赖,是最轻量化的解决方案
内容的提问来源于stack exchange,提问作者salamandra
相关产品推荐
相关产品推荐

