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

基于Django 1.11+DRF的ERP API多应用权限实现方案咨询

跨多应用的Django + DRF权限控制实现方案

作为长期用Django和DRF做企业级API开发的开发者,结合你这个ERP项目的场景,我给你梳理一套落地性强的跨应用权限实现方案,都是我实际项目里验证过的思路:

一、先搭好基础:基于Django原生权限系统扩展

Django自带的django.contrib.auth已经提供了用户、组、权限的核心框架,这是跨应用权限管理的最佳起点,完全不用重复造轮子。

1. 为各应用模型定义自定义权限

每个应用的模型可以在Meta类里添加贴合业务的自定义权限,让权限颗粒度更细:

  • Accounts应用(用户资料与认证):
# accounts/models.py
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    # 你的自定义字段(比如手机号、部门)
    class Meta:
        permissions = [
            ("view_all_profiles", "Can view all user profiles"),
            ("edit_own_profile", "Can edit own user profile"),
        ]
  • HR应用(员工管理):
# hr/models.py
from django.db import models

class Employee(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    # 其他员工字段(入职日期、岗位等)
    class Meta:
        permissions = [
            ("manage_employees", "Can create/edit/delete employees"),
            ("view_employee_details", "Can view employee details"),
        ]
  • Payroll应用(薪资管理):
# payroll/models.py
class SalarySlip(models.Model):
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    # 薪资字段(应发、实发、扣款等)
    class Meta:
        permissions = [
            ("generate_salary_slips", "Can generate salary slips"),
            ("view_salary_slips", "Can view salary slips"),
            ("approve_salary_slips", "Can approve salary slips"),
        ]

这些权限会自动被Django的权限系统纳入管理,跨应用也能无缝识别。

2. 用组(Group)批量管理权限

手动给每个用户加权限效率太低,建议创建对应业务角色的组,把权限批量分配给组,再把用户加入组:

  • HR管理员组:包含HR应用的所有权限 + Accounts的view_all_profiles
  • 财务组:包含Payroll应用的所有权限
  • 普通员工组:只有edit_own_profile、view_employee_details(仅限自己)、view_salary_slips(仅限自己)

可以写个管理命令初始化这些组:

# accounts/management/commands/init_groups.py
from django.core.management.base import BaseCommand
from django.contrib.auth.models import Group, Permission

class Command(BaseCommand):
    def handle(self, *args, **options):
        # 创建HR管理员组
        hr_admin_group, _ = Group.objects.get_or_create(name='HR Admin')
        hr_perms = Permission.objects.filter(content_type__app_label='hr')
        accounts_perms = Permission.objects.filter(codename='view_all_profiles')
        hr_admin_group.permissions.add(*hr_perms, *accounts_perms)

        # 创建财务组
        finance_group, _ = Group.objects.get_or_create(name='Finance')
        payroll_perms = Permission.objects.filter(content_type__app_label='payroll')
        finance_group.permissions.add(*payroll_perms)

        # 创建普通员工组
        employee_group, _ = Group.objects.get_or_create(name='Employee')
        employee_perms = Permission.objects.filter(codename__in=[
            'edit_own_profile', 'view_employee_details', 'view_salary_slips'
        ])
        employee_group.permissions.add(*employee_perms)

运行python manage.py init_groups就能快速初始化组和权限。

二、DRF层面的接口权限控制

因为是API项目,需要结合DRF的权限类实现接口级别的校验:

1. 全局默认权限配置

先在settings.py里设置全局默认权限,确保所有接口都经过基础校验:

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
        'rest_framework.permissions.DjangoModelPermissions',
    ]
}

DjangoModelPermissions会自动对应模型的view/add/change/delete权限,加上我们自定义的权限,能覆盖大部分常规场景。

2. 自定义权限类处理精细化场景

比如“普通员工只能查看自己的薪资单”这种个性化需求,写个自定义权限类:

# payroll/permissions.py
from rest_framework import permissions

class IsOwnerOrAdmin(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        # 管理员或财务可以查看所有薪资单
        if request.user.has_perm('payroll.approve_salary_slips'):
            return True
        # 普通员工只能查看自己的
        return obj.employee.user == request.user

然后在视图集里使用:

# payroll/views.py
from rest_framework import viewsets
from .models import SalarySlip
from .serializers import SalarySlipSerializer
from .permissions import IsOwnerOrAdmin

class SalarySlipViewSet(viewsets.ModelViewSet):
    queryset = SalarySlip.objects.all()
    serializer_class = SalarySlipSerializer
    permission_classes = [IsOwnerOrAdmin]

3. 函数视图的权限装饰器

如果用函数式视图,直接用DRF的装饰器:

# hr/views.py
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions
from .models import Employee
from .serializers import EmployeeSerializer

@api_view(['GET'])
@permission_classes([IsAuthenticated, DjangoModelPermissions])
def employee_list(request):
    employees = Employee.objects.all()
    serializer = EmployeeSerializer(employees, many=True)
    return Response(serializer.data)

三、跨应用权限的统一管理与校验

1. 封装权限校验工具函数

在Accounts应用里写个工具函数,方便其他应用统一调用校验逻辑:

# accounts/utils.py
def has_permission(user, perm_full_code):
    """检查用户是否拥有指定权限(格式:app.codename)"""
    return user.has_perm(perm_full_code)

def is_hr_admin(user):
    return user.groups.filter(name='HR Admin').exists() or user.is_superuser

def is_finance(user):
    return user.groups.filter(name='Finance').exists() or user.is_superuser

其他应用直接导入使用:

# payroll/views.py
from accounts.utils import is_finance

def generate_salary_slip(request):
    if not is_finance(request.user):
        return Response({'error': 'Permission denied'}, status=403)
    # 生成薪资单的业务逻辑...

2. 用Django Admin统一管理

Django Admin默认已经支持跨应用管理用户、组、权限,权限会按应用分类显示,直接在Admin里就能给用户/组分配不同应用的权限,操作非常直观。

四、实用落地技巧

  • Django信号自动分配默认组:监听用户创建事件,自动给新用户分配普通员工组,减少手动操作:
# accounts/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import CustomUser
from django.contrib.auth.models import Group

@receiver(post_save, sender=CustomUser)
def assign_default_group(sender, instance, created, **kwargs):
    if created:
        employee_group = Group.objects.get(name='Employee')
        instance.groups.add(employee_group)

记得在accounts/apps.py里注册信号:

# accounts/apps.py
from django.apps import AppConfig

class AccountsConfig(AppConfig):
    name = 'accounts'
    def ready(self):
        import accounts.signals
  • 查看权限分配情况:在Django shell里可以快速验证权限:
python manage.py shell
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username='test')
>>> user.has_perm('hr.manage_employees')
>>> user.groups.all()

内容的提问来源于stack exchange,提问作者Philip Mutua

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:37:28