You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让Django2.1.4站点所有URL仅对注册用户开放?自定义Middleware失效

解决Django 2.1.4自定义权限中间件失效问题

我来帮你排查这个中间件的问题——你的代码有两个关键错误导致它没生效,咱们一步步来修正:

问题根源

  1. 新中间件模式不自动执行process_request方法:你用了Django 1.10+引入的新中间件结构(包含__init____call__方法),但仍然保留了旧模式的process_request方法,这个方法在新结构中不会被自动调用。
  2. is_authenticated调用方式错误:Django 2.1中request.user.is_authenticated是一个属性,不是方法,你加了括号()会导致逻辑判断出错(甚至语法错误)。
  3. 缺少登录页排除逻辑:如果不排除登录页面,未登录用户会被无限重定向到登录页,陷入循环。

修正后的中间件代码(推荐新模式)

from django.http import HttpResponseRedirect
from django.urls import reverse

class MyAuthorization:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # 请求到达视图前的权限验证逻辑(必须放在get_response调用前)
        # 排除登录页面,避免无限重定向
        login_url = reverse('login')  # 替换成你实际的登录URL名称
        if not request.user.is_authenticated and request.path != login_url:
            return HttpResponseRedirect(login_url)

        # 继续执行后续中间件和视图
        response = self.get_response(request)

        # 这里可以添加响应返回后的处理逻辑(如果需要)
        return response

另一种兼容旧模式的写法(不推荐长期使用)

如果你更习惯旧的process_request写法,可以继承MiddlewareMixin来兼容:

from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin

class MyAuthorization(MiddlewareMixin):
    def process_request(self, request):
        login_url = reverse('login')
        if not request.user.is_authenticated and request.path != login_url:
            return HttpResponseRedirect(login_url)
        return None

关键注意事项

  • 中间件顺序:你的settings.pyMyAuthorization放在AuthenticationMiddleware之后是正确的,因为AuthenticationMiddleware会把用户对象绑定到request.user上,你的中间件才能正确获取用户认证状态。
  • 避免硬编码URL:用reverse('login')代替硬编码的'/',这样如果后续修改登录URL配置,不需要修改中间件代码。
  • 测试边缘情况:记得测试登录用户访问、未登录用户访问非登录页、未登录用户访问登录页这几种场景,确保逻辑正常。

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

火山引擎 最新活动