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

如何在Django中创建中间件检查用户权限?含装饰器与选型疑问

Django自定义Admin面板权限控制完整方案

一、用中间件实现Admin面板全局权限校验

你不需要在中间件里嵌套@permission_required装饰器,直接在中间件中编写路径匹配+权限判断逻辑更高效,能一次性覆盖所有adminpanel请求:

1. 函数式中间件实现

写法简洁,适合逻辑简单的场景:

# middleware.py
from django.shortcuts import redirect
from django.urls import reverse
from .models import UserAccount

def admin_panel_auth_middleware(get_response):
    def middleware(request):
        # 匹配adminpanel前缀的请求(根据你的实际URL规则调整)
        if request.path.startswith('/adminpanel/'):
            # 未登录用户直接跳首页
            if not request.user.is_authenticated:
                return redirect(reverse('home'))
            # 检查用户是否为管理员
            try:
                user_account = request.user.useraccount
                if user_account.is_admin != 'True':
                    return redirect(reverse('home'))
            except UserAccount.DoesNotExist:
                # 无关联UserAccount的用户直接拒绝访问
                return redirect(reverse('home'))
        # 符合条件或非adminpanel请求,继续处理后续逻辑
        response = get_response(request)
        return response
    return middleware

在settings.py的MIDDLEWARE列表中注册该中间件:

MIDDLEWARE = [
    # 其他中间件...
    'your_app_name.middleware.admin_panel_auth_middleware',
]

2. 类式中间件实现

结构规范,适合逻辑复杂、需要扩展的场景:

# middleware.py
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
from .models import UserAccount

class AdminPanelAuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        if request.path.startswith('/adminpanel/'):
            if not request.user.is_authenticated:
                return redirect(reverse('home'))
            try:
                user_account = request.user.useraccount
                if user_account.is_admin != 'True':
                    return redirect(reverse('home'))
            except UserAccount.DoesNotExist:
                return redirect(reverse('home'))
        return None

同样在settings.py中注册:

MIDDLEWARE = [
    # 其他中间件...
    'your_app_name.middleware.AdminPanelAuthMiddleware',
]

二、函数式vs类式中间件的核心区别

  • 写法复杂度:函数式代码更精简,几行就能完成基础校验;类式需要继承MiddlewareMixin(Django3.2+也可直接实现__call__方法),结构更规整。
  • 扩展性:类式可通过继承、重写方法实现功能扩展,比如同时处理请求前校验和请求后响应;函数式逻辑变复杂后会变得臃肿,不易维护。
  • 适用场景:简单的全局权限校验用函数式足够;如果需要多阶段处理、复用逻辑,类式更合适。
  • 兼容性:类式兼容旧版Django,函数式是Django1.10+推荐的现代写法,更贴合函数式编程风格。

三、现有创建用户代码的优化建议

你的createNewUser函数有几个关键问题需要修正:

  1. 密码加密存储:直接用create方法设置密码会明文存储,必须用set_password加密:
# 修正密码处理逻辑
user = User.objects.create(username=request.POST.get('username'), email=request.POST.get('email'))
user.set_password(request.POST.get('password'))  # 对密码进行加密
user.save()
  1. is_admin字段优化:建议将is_admin存为布尔值(如果你的UserAccount模型用BooleanField),而非字符串:
is_admin = request.POST.get('is_admin') == 'True'
useraccount = UserAccount.objects.create(user=user, is_admin=is_admin)
  1. 权限清理逻辑调整:确保用户保存后再清理权限,避免无效操作:
if not is_admin:
    user.user_permissions.clear()
user.save()

四、关于@permission_required的使用说明

@permission_required适合单个视图的细粒度权限校验,但如果要给整个adminpanel的所有视图统一加校验,用中间件更高效,无需逐个视图添加装饰器。如果个别视图有特殊权限需求,可以在中间件校验通过后,再给该视图额外添加装饰器做二次校验。

内容的提问来源于stack exchange,提问作者Timur Arazmedov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 16:57:31