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

用户登录后个人资料与注销链接错误重定向至登录页问题排查

问题排查:Django登录后点击个人资料/注销被重定向至登录页

背景

正在开发一个Django项目,已实现用户认证、个人资料及注销功能。当前遇到的问题是:用户登录后,点击导航栏中的个人资料或注销链接时,会被重定向至登录页,而非进入个人资料页或执行注销操作。

预期行为

  • 个人资料链接:用户登录后应跳转至其个人资料页。
  • 注销链接:应注销用户并跳转至首页。

当前配置

模板(base.html):

{% if logged_in %}
    <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
        {{ customer_name }}
    </a>
    <ul class="dropdown-menu" aria-labelledby="userDropdown">
        <li><a class="dropdown-item" href="{% url 'profile' %}?email={{ customer_email }}">Profile</a></li>
        <li><a class="dropdown-item" href="{% url 'logout' %}">Logout</a></li>
    </ul>
{% else %}
    <a class="nav-link" href="{% url 'login' %}">Login</a>
{% endif %}

视图(Views):

from django.shortcuts import redirect, render
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .models import customer

@login_required
def profile_view(request):
    email = request.GET.get('email')
    if email:
        try:
            user = customer.objects.get(email=email)
            if user.id == request.session.get('customer_id'):
                return render(request, 'profile.html', {'user': user})
            else:
                return redirect('index')
        except customer.DoesNotExist:
            return redirect('index')
    else:
        return redirect('index')

def logout_view(request):
    request.session.flush()
    auth_logout(request)
    return redirect('index')

def login_view(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')

        try:
            customer = customer.objects.get(email=email)
            if customer.check_password(password):
                request.session['customer_id'] = customer.id
                request.session['logged_in'] = True
                request.session['customer_name'] = f"{customer.first_name} {customer.last_name}"
                request.session['customer_email'] = customer.email
                messages.success(request, "Logged in!!")
                return redirect('index')
            else:
                messages.error(request, 'Incorrect password')
        except customer.DoesNotExist:
            messages.error(request, 'Email not found')

    return render(request, 'login.html')

URL配置:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('login/', views.login_view, name='login'),
    path('logout/', views.logout_view, name='logout'),
    path('profile/', views.profile_view, name='profile'),
]

会话管理:

  • 会话变量在login_view中设置,在logout_view中清除。

已执行的调试步骤:

  • 在不同视图中打印会话数据,确认customer_id和customer_name已正确设置。
  • 观察到点击个人资料或注销链接始终重定向至登录页。

求助问题

请帮忙排查为何这些链接会重定向至登录页,而非正常显示个人资料或执行注销操作?尤其需要协助验证会话处理逻辑,确保重定向正常。


问题分析与解决方案

核心问题:Django内置认证与自定义会话不兼容

你混用了Django的@login_required装饰器和自定义会话变量,但未正确调用Django内置的auth_login方法,导致@login_required判定用户未登录,直接触发登录页重定向。

具体修复步骤

1. 修复登录视图,激活Django内置认证

在login_view中,验证密码通过后必须调用auth_login(request, customer),让Django认证系统识别当前用户:

def login_view(request):
    if request.method == 'POST':
        email = request.POST.get('email')
        password = request.POST.get('password')

        try:
            customer = customer.objects.get(email=email)
            if customer.check_password(password):
                # 关键:调用Django内置登录方法,同步认证状态
                auth_login(request, customer)
                request.session['customer_id'] = customer.id
                request.session['logged_in'] = True
                request.session['customer_name'] = f"{customer.first_name} {customer.last_name}"
                request.session['customer_email'] = customer.email
                messages.success(request, "Logged in!!")
                return redirect('index')
            else:
                messages.error(request, 'Incorrect password')
        except customer.DoesNotExist:
            messages.error(request, 'Email not found')

    return render(request, 'login.html')

2. 优化个人资料视图,移除冗余URL参数

个人资料视图无需通过URL传递email,直接从request.user获取当前登录用户,既安全又简洁:

@login_required
def profile_view(request):
    # 直接从request.user获取已登录的customer对象
    user = request.user
    return render(request, 'profile.html', {'user': user})

对应的模板链接也可简化:

<li><a class="dropdown-item" href="{% url 'profile' %}">Profile</a></li>

3. 确认用户模型配置(必要前提)

确保customer模型继承Django的AbstractBaseUser或AbstractUser,并在settings.py中配置自定义用户模型:

# settings.py
AUTH_USER_MODEL = '你的应用名称.customer'

若未继承用户基类,auth_login无法正常工作,需先调整模型结构。

4. 简化注销视图(可选)

auth_logout已自动清除Django认证会话,无需额外调用request.session.flush()(如需清除自定义会话变量可保留):

def logout_view(request):
    auth_logout(request)
    # 如需清除自定义会话变量可保留以下代码
    # request.session.flush()
    messages.success(request, "Logged out successfully")
    return redirect('index')

重定向原因说明

@login_required装饰器依赖Django内置认证系统,检查request.user.is_authenticated状态。之前仅设置自定义会话变量,未调用auth_login,导致request.user仍为匿名用户,装饰器直接触发登录页重定向。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 10:26:00