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

Django会话超时登录后如何固定重定向至首页而非原访问页

问题说明

当用户在任意页面停留到会话超时,点击跳转到其他页面的链接时,会被自动重定向到登录页;默认情况下完成登录后,系统会跳转到用户之前尝试访问的目标页,但需求是所有场景下登录成功后都固定跳转到首页home.html。目前已经在settings.py中配置了LOGIN_REDIRECT_URL = 'home',但配置没有生效。

现有项目配置

项目所有视图都要求登录后才能访问:

  • 类视图统一用装饰器加登录校验:
@method_decorator([login_required], name='dispatch')
class QuestionListView(PermissionRequiredMixin, ListView):
    # 业务逻辑代码
  • 函数视图直接用@login_required装饰器校验,首页视图示例:
@login_required
def home(request):
    # 首页业务逻辑

项目全程使用Django原生auth模块,没有自定义登录视图,登录模板login.html表单代码如下:

<form method="post">
  {% csrf_token %}
  {{ form|crispy }}
  <a class="button secondaryAction" href="{% url 'password_reset' %}">Forgot Password?</a>
  <button type="submit" class="btn btn-secondary mt-2 pl-4">Log In</button>
</form>
问题根因

查看Django框架django.contrib.auth.views模块源码,重定向逻辑在RedirectURLMixin类中实现:

class RedirectURLMixin:
    next_page = None
    redirect_field_name = REDIRECT_FIELD_NAME
    success_url_allowed_hosts = set()

    def get_success_url(self):
        return self.get_redirect_url() or self.get_default_redirect_url()

    def get_redirect_url(self):
        """Return the user-originating redirect URL if it's safe."""
        redirect_to = self.request.POST.get(
            self.redirect_field_name, self.request.GET.get(self.redirect_field_name)
        )
        url_is_safe = url_has_allowed_host_and_scheme(
            url=redirect_to,
            allowed_hosts=self.get_success_url_allowed_hosts(),
            require_https=self.request.is_secure(),
        )
        return redirect_to if url_is_safe else ""

    def get_success_url_allowed_hosts(self):
        return {self.request.get_host(), *self.success_url_allowed_hosts}

    def get_default_redirect_url(self):
        """Return the default redirect URL."""
        if self.next_page:
            return resolve_url(self.next_page)
        raise ImproperlyConfigured("No URL to redirect to. Provide a next_page.")

之前的判断完全准确:会话超时后点击链接触发登录跳转时,@login_required装饰器会自动在登录页URL上拼接next参数,记录用户原本要访问的地址。而原生登录视图的逻辑是优先读取合法的next参数作为跳转地址,只有next不存在或非法时,才会读取LOGIN_REDIRECT_URL配置的默认地址,所以只修改这个配置没法覆盖带next参数的登录场景。

实现方案

需求是临时让所有登录成功的请求统一跳首页,让用户能看到首页的公告横幅,不需要保留原跳转逻辑,两种实现方式二选一即可:

方案1:修改模板固定next参数(改动最小,适合临时需求)

Django登录模板如果没有显式定义next表单字段,当URL带next参数时,框架会自动生成隐藏input提交这个值。只要在表单里手动加一个固定值为首页地址的next隐藏域,就会覆盖URL携带的参数:
在login.html的表单中,{% csrf_token %}后添加一行:

<input type="hidden" name="next" value="{% url 'home' %}">

修改后表单完整结构:

<form method="post">
  {% csrf_token %}
  <!-- 新增固定next参数的隐藏域 -->
  <input type="hidden" name="next" value="{% url 'home' %}">
  {{ form|crispy }}
  <a class="button secondaryAction" href="{% url 'password_reset' %}">Forgot Password?</a>
  <button type="submit" class="btn btn-secondary mt-2 pl-4">Log In</button>
</form>

这个方案不需要改任何视图、路由代码,后续公告下线要恢复原跳转逻辑,直接删掉这行隐藏域即可。

方案2:重写登录视图的跳转逻辑(扩展性更好)

如果后续还要扩展登录相关逻辑(比如记录登录时间、登录IP),可以继承原生LoginView重写跳转方法,强制返回首页地址:

  1. 在views.py中自定义登录视图:
from django.contrib.auth.views import LoginView
from django.urls import reverse_lazy

class FixedRedirectLoginView(LoginView):
    def get_success_url(self):
        # 忽略所有next参数,统一跳首页
        return reverse_lazy('home')
  1. 修改根路由urls.py中的登录路由,将原来指向原生LoginView的配置替换为自定义视图:
from django.urls import path
from yourapp.views import FixedRedirectLoginView

urlpatterns = [
    # 其他原有路由...
    # 替换原有的login路由配置
    path('accounts/login/', FixedRedirectLoginView.as_view(template_name='login.html'), name='login'),
    # 其余auth相关路由无需修改
]

两种方案都不会影响现有@login_required装饰器、权限校验的正常运行,登录后所有用户都会先进入首页看到公告,完全满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:16:21