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

从Django 2.0升级至4.2后调用login()函数出现会话提前删除错误

Django 4.2升级后login()调用出现"The request's session was deleted before the request completed"错误的解决思路

问题场景

将Django从2.0升级到4.2后,在权限类的handle_no_permission方法中调用login()函数时,出现以下错误提示:

The request's session was deleted before the request completed. The user may have logged out in a concurrent request, for example.

但实际用户登录是成功的——login()调用前后self.request.user.is_authenticated分别返回False和True,功能逻辑正常,仅抛出该错误。

核心原因

Django 3.1+对session管理增加了更严格的状态检查:当请求中存在先删除旧session、再创建新session的操作时(比如此处登录时会清理原匿名用户的session,再生成登录用户的session),如果后续代码继续触发请求生命周期的session校验(比如调用父类的handle_no_permission),就会触发这个错误提示。

旧版本Django(2.0)没有这类严格校验,所以不会出现该问题。

解决方案

方案1:登录成功后直接返回响应,终止后续流程

当前代码在登录成功后仍调用super().handle_no_permission(),父类方法会继续执行权限失败的后续逻辑,和已完成的登录操作产生session状态冲突。修改后代码如下:

def handle_no_permission(self):
    if self.request.user.is_authenticated and not self.test_func() and not self.is_source_email():
        self.raise_exception = True
    if all(x in self.request.GET.keys() for x in ["token", "source"]):
        if self.is_source_email():
            token_from_url = self.request.GET.get("token")
            deficiency_id = self.kwargs.get('deficiency_id')
            try:
                login_token = ProviderLoginToken.objects.get(key=token_from_url, deficiency_id=deficiency_id)
                if login_token.active:
                    user = login_token.provider.user
                    user.backend = "django.contrib.auth.backends.ModelBackend"
                    login(self.request, user, backend=user.backend)
                    # 登录成功后直接返回目标页面/重定向,不再执行父类方法
                    return redirect("your_target_url_name")  # 替换为实际的成功跳转地址
                else:
                    return render(self.request, "500_invalid_quick_amend_link.html")
            except ProviderLoginToken.DoesNotExist:
                return render(self.request, "500_invalid_quick_amend_link.html")

    return super().handle_no_permission()

方案2:手动清理旧session后再登录

如果必须保留后续流程,可以在调用login()前主动清理当前无效session,避免状态冲突:

# 在login()调用前添加以下代码
if self.request.session.session_key:
    self.request.session.flush()

# 原登录逻辑
login(self.request, user, backend=user.backend)

关键说明

这个错误属于Django新版本的session校验机制带来的"误报"——并非真的有并发登出操作,而是单请求内的session状态变更触发了校验逻辑。只要确保登录操作完成后,不再触发可能干扰session状态的后续权限逻辑,就能解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 08:10:44