Django中按分支管理用户权限的最优方案咨询
Django按分支管理用户权限的最佳方案
针对你提出的「用户在不同分支拥有不同角色权限,且分支与角色组相互独立」的需求,最佳方案是通过扩展模型建立「用户-分支-角色」的关联关系,同时自定义分支维度的权限校验逻辑,避免为每个用户-分支组合重复创建组。
核心实现步骤
1. 定义基础模型
先创建分支模型,再通过中间表关联用户、分支和Django自带的Group(角色),同时可扩展额外属性(如邮件接收开关):
from django.db import models from django.contrib.auth.models import User, Group class Branch(models.Model): name = models.CharField(max_length=100, unique=True, verbose_name="分支名称") code = models.CharField(max_length=20, unique=True, verbose_name="分支编码") def __str__(self): return self.name class UserBranchRole(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="branch_roles", verbose_name="用户") branch = models.ForeignKey(Branch, on_delete=models.CASCADE, verbose_name="所属分支") group = models.ForeignKey(Group, on_delete=models.CASCADE, verbose_name="角色组") receive_emails = models.BooleanField(default=True, verbose_name="接收分支员工邮件") class Meta: unique_together = ("user", "branch", "group") # 避免重复绑定同一用户-分支-角色组合 verbose_name = "用户分支角色"
2. 自定义分支权限校验函数
Django默认的user.has_perm()是全局权限校验,我们需要编写函数,结合用户在目标分支下的角色组来判断权限:
def has_branch_permission(user, perm_codename, branch): """ 校验用户在指定分支下是否拥有目标权限 :param user: 当前用户对象 :param perm_codename: 权限编码(如'change_employee') :param branch: 目标分支对象 :return: bool,是否拥有权限 """ # 获取用户在该分支下的所有角色组ID user_group_ids = user.branch_roles.filter(branch=branch).values_list("group__id", flat=True) # 检查这些组是否包含目标权限 return user.groups.filter(id__in=user_group_ids, permissions__codename=perm_codename).exists()
3. 视图中使用分支权限校验
在视图里,先获取当前操作的分支,再调用自定义函数校验权限:
from django.shortcuts import get_object_or_404 from django.http import HttpResponseForbidden from .models import Branch from .utils import has_branch_permission def edit_employee(request, branch_code, employee_id): branch = get_object_or_404(Branch, code=branch_code) # 校验用户在该分支下是否有编辑员工的权限 if not has_branch_permission(request.user, "change_employee", branch): return HttpResponseForbidden("无此分支的员工编辑权限") # 后续业务逻辑...
4. 模板中权限校验支持
通过自定义模板标签,让模板也能直接判断分支权限:
# 在app下创建templatetags/branch_perms.py from django import template from ..utils import has_branch_permission register = template.Library() @register.simple_tag def has_branch_perm(user, perm_codename, branch): return has_branch_permission(user, perm_codename, branch)
模板中使用:
{% load branch_perms %} {% if has_branch_perm request.user 'change_employee' current_branch %} <button type="button" class="btn btn-primary">编辑员工</button> {% else %} <button type="button" class="btn btn-secondary" disabled>无编辑权限</button> {% endif %}
5. 分支邮件接收控制
发送分支专属邮件时,通过UserBranchRole的receive_emails字段过滤用户:
from django.core.mail import send_mail from .models import Branch def send_branch_announcement(branch_code, subject, content): branch = get_object_or_404(Branch, code=branch_code) # 获取该分支下需要接收邮件的用户 target_users = User.objects.filter( branch_roles__branch=branch, branch_roles__receive_emails=True ).distinct() # 批量发送邮件 send_mail( subject=subject, message=content, from_email="admin@company.com", recipient_list=[user.email for user in target_users] )
6. 后台管理优化
通过Admin内联,让管理员可以直接在用户编辑页面分配不同分支的角色:
from django.contrib import admin from django.contrib.auth.models import User from .models import Branch, UserBranchRole class UserBranchRoleInline(admin.TabularInline): model = UserBranchRole extra = 1 class CustomUserAdmin(admin.ModelAdmin): inlines = [UserBranchRoleInline] # 替换默认的User Admin admin.site.unregister(User) admin.site.register(User, CustomUserAdmin) admin.site.register(Branch)
方案优势
- 分支与角色组完全解耦:同一角色(如HR Manager)可复用在任意分支,无需重复创建组
- 权限粒度精确:可针对每个用户-分支-角色组合单独配置权限和附加属性
- 扩展性强:后续可轻松添加分支级别的其他规则(如数据隔离、审批流程)
内容的提问来源于stack exchange,提问作者joseph Kalash
相关产品推荐
相关产品推荐

