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

能否针对单个视图实现分组动态权限管理?适配Django各类视图

Django 扩展分组权限至所有视图(含REST/MVC)

1. 自定义视图级权限模型

Django默认权限基于模型,我们需要创建自定义模型来存储视图与HTTP方法的权限关联:

# models.py
from django.db import models
from django.contrib.auth.models import Group

class ViewPermission(models.Model):
    VIEW_METHODS = [
        ('GET', 'GET'),
        ('POST', 'POST'),
        ('PUT', 'PUT'),
        ('DELETE', 'DELETE'),
        ('PATCH', 'PATCH'),
    ]
    view_name = models.CharField(max_length=255, unique=True, verbose_name="视图名称")
    http_method = models.CharField(max_length=10, choices=VIEW_METHODS, verbose_name="HTTP方法")
    groups = models.ManyToManyField(Group, related_name='view_permissions', verbose_name="关联分组")

    class Meta:
        unique_together = ('view_name', 'http_method')
        verbose_name = "视图权限"
        verbose_name_plural = "视图权限"

    def __str__(self):
        return f"{self.view_name} - {self.http_method}"

在admin.py注册该模型,方便后台管理:

# admin.py
from django.contrib import admin
from .models import ViewPermission

class ViewPermissionAdmin(admin.ModelAdmin):
    list_display = ('view_name', 'http_method', 'get_groups')
    filter_horizontal = ('groups',)

    def get_groups(self, obj):
        return ", ".join([group.name for group in obj.groups.all()])
    get_groups.short_description = "关联分组"

admin.site.register(ViewPermission, ViewPermissionAdmin)

2. 实现权限验证逻辑

函数视图装饰器(适用于MVC函数视图)

# decorators.py
from django.http import HttpResponseForbidden
from .models import ViewPermission

def view_permission_required(view_name):
    def decorator(view_func):
        def wrapper(request, *args, **kwargs):
            method = request.method.upper()
            # 检查当前用户所属分组是否拥有该视图的对应方法权限
            has_perm = ViewPermission.objects.filter(
                view_name=view_name,
                http_method=method,
                groups__in=request.user.groups.all()
            ).exists()
            if not has_perm and not request.user.is_superuser:
                return HttpResponseForbidden("无访问权限")
            return view_func(request, *args, **kwargs)
        return wrapper
    return decorator

类视图Mixin(适用于MVC类视图和DRF视图)

# mixins.py
from django.http import HttpResponseForbidden
from rest_framework import permissions
from .models import ViewPermission

class ViewPermissionMixin:
    view_name = None  # 需在子类中指定视图名称

    def has_permission(self, request, *args, **kwargs):
        if request.user.is_superuser:
            return True
        method = request.method.upper()
        return ViewPermission.objects.filter(
            view_name=self.view_name,
            http_method=method,
            groups__in=request.user.groups.all()
        ).exists()

    # 适配Django类视图
    def dispatch(self, request, *args, **kwargs):
        if not self.has_permission(request):
            return HttpResponseForbidden("无访问权限")
        return super().dispatch(request, *args, **kwargs)

# DRF专用Mixin(可选,继承DRF的BasePermission)
class DRFViewPermission(permissions.BasePermission):
    view_name = None

    def has_permission(self, request, view):
        if request.user.is_superuser:
            return True
        method = request.method.upper()
        return ViewPermission.objects.filter(
            view_name=self.view_name,
            http_method=method,
            groups__in=request.user.groups.all()
        ).exists()

3. 后台配置分组权限

运行makemigrations和migrate创建表后,进入Django后台:

  • 找到「视图权限」模块,添加两条权限:
    • 视图名称:Article,HTTP方法:GET,关联分组:Author、Reader
    • 视图名称:Article,HTTP方法:POST,关联分组:Author
  • 后续可随时在后台给任意分组添加/移除任意视图的任意方法权限

4. 在视图中应用权限

MVC函数视图

# views.py
from django.shortcuts import render
from .decorators import view_permission_required

@view_permission_required(view_name="Article")
def article_view(request):
    if request.method == 'GET':
        # 处理GET请求逻辑
        return render(request, 'article/list.html')
    elif request.method == 'POST':
        # 处理POST请求逻辑
        return render(request, 'article/success.html')

MVC类视图

# views.py
from django.views import View
from .mixins import ViewPermissionMixin

class ArticleView(ViewPermissionMixin, View):
    view_name = "Article"

    def get(self, request):
        # 处理GET逻辑
        pass

    def post(self, request):
        # 处理POST逻辑
        pass

DRF视图

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .mixins import DRFViewPermission

class ArticleAPIView(APIView):
    permission_classes = [DRFViewPermission]
    view_name = "Article"

    def get(self, request):
        return Response({"message": "GET请求允许"})

    def post(self, request):
        return Response({"message": "POST请求允许"})

内容的提问来源于stack exchange,提问作者Shukurullo Makhammadjanov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:02:08