求Django AbstractBaseUser自定义用户模型has_perm()角色权限实现示例
基于角色的Django自定义用户模型权限实现方案
以下提供两种常用实现方案,可根据业务场景选择:
方案1:重写权限校验方法(轻量实现)
你原有代码中has_perm和has_module_perms直接返回True,会导致所有用户都拥有全部权限,首先修改这两个方法的逻辑,加入角色判断即可:
class User(AbstractBaseUser, PermissionsMixin): class RoleChoices(models.TextChoices): admin = 'Admin', _('Admin') cashier = 'Cashier', _('Cashier') waiter = 'Waiter', _('Waiter') courier = 'Courier', _('Courier') customer = 'Customer', _('Customer') # 原有字段保持不变 username = models.CharField(_('username'), unique=True, max_length=100) name = models.CharField(_('name'), max_length=100) surname = models.CharField(_('surname'), max_length=100) phone_number = models.CharField(_('phone_number'), max_length=100, null=True, default='Invalid Phone Number') role = models.CharField(max_length=50, choices=RoleChoices.choices, default=RoleChoices.customer) active = models.BooleanField(default=True) date_joined = models.DateTimeField(auto_now_add=True) USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['name', 'surname'] class Meta: ordering = ['date_joined', ] def __str__(self): return self.username # 定义每个角色对应的权限列表,格式为「应用名.权限codename」 @property def role_permissions(self): permission_map = { self.RoleChoices.admin: ['*'], # 管理员拥有所有权限 self.RoleChoices.cashier: ['order.view_order', 'order.change_payment_status'], self.RoleChoices.waiter: ['order.add_order', 'order.view_order', 'table.change_table_status'], self.RoleChoices.courier: ['order.view_delivery_order', 'order.change_delivery_status'], self.RoleChoices.customer: ['order.view_my_order', 'order.add_order'] } return permission_map.get(self.role, []) def has_perm(self, perm, obj=None): # 超级用户直接放行 if self.is_superuser: return True perms = self.role_permissions # 管理员角色通配所有权限 if '*' in perms: return True # 校验当前权限是否在角色权限列表中 return perm in perms def has_module_perms(self, app_label): if self.is_superuser or self.role == self.RoleChoices.admin: return True # 校验是否有该应用下的任意权限 app_perms = [p for p in self.role_permissions if p.startswith(f"{app_label}.")] return len(app_perms) > 0 @property def is_active(self): return self.active objects = CustomUserManager()
你可以根据自己的业务需求,直接调整role_permissions映射关系中的权限列表即可。
方案2:结合Django权限组实现(灵活可配置)
如果需要后续在后台动态调整角色对应权限,不需要修改代码,可以结合Django自带的Group权限组功能,用信号实现角色变更时自动同步权限组:
- 首先删除你原有自定义的
has_perm和has_module_perms方法,直接使用PermissionsMixin提供的原生校验逻辑 - 在应用下新建
signals.py定义信号逻辑:
from django.db.models.signals import post_save from django.dispatch import receiver from django.contrib.auth.models import Group from .models import User @receiver(post_save, sender=User) def sync_user_role_permissions(sender, instance, created, **kwargs): # 清空用户所有原有权限组 instance.groups.clear() # 获取角色对应的权限组,不存在则自动创建 group, _ = Group.objects.get_or_create(name=instance.role) # 把用户加入对应权限组 instance.groups.add(group)
- 在
apps.py中注册信号:
from django.apps import AppConfig class YourAppConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = '你的应用名称' def ready(self): import 你的应用名称.signals
配置完成后,你只需要在Django后台给每个角色对应的权限组配置对应权限即可,无需修改代码。
选型参考
- 方案1适合角色和权限固定的场景,代码逻辑直观不需要额外配置
- 方案2适合权限需要经常调整的场景,复用Django原生权限体系,兼容性更好
内容的提问来源于stack exchange,提问作者Sequery
相关产品推荐
相关产品推荐

