You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求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权限组功能,用信号实现角色变更时自动同步权限组:

  1. 首先删除你原有自定义的has_perm和has_module_perms方法,直接使用PermissionsMixin提供的原生校验逻辑
  2. 在应用下新建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)
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 15:45:03