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

Django登录后无法跳转至目标页面问题求助

问题:LoginRequiredMixin 登录后 next_url 重定向失效,总是跳转到首页

我是Django新手,正在测试LoginRequiredMixin与next_url重定向功能。登录功能正常,但登录后总是跳转到首页,而非用户想要访问的页面。例如访问链接http://localhost:8000/post/login/?next=/post/1/,登录后却跳转到http://localhost:8000/post/。

相关代码片段

views.py

def loginUser(request):
    if request.method == 'POST':
        form = Login(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                next_url = request.GET.get('next', None)
                post_id = request.GET.get('post_id', None)
                print("Next URL:", next_url)
                print("Post ID:", post_id)
                if next_url:
                    return HttpResponseRedirect(next_url)
                else:
                    return redirect('posts:posts-index')
    else:
        form = Login()
    return render(request, 'posts/login.html', {'form': form})

class Content(LoginRequiredMixin, DetailView):
    template_name = 'posts/post.html'
    context_object_name = 'post'
    login_url = 'login/'

    def handle_no_permission(self):
        if not self.request.user.is_authenticated:
            post_id = self.kwargs.get('pk', None)
            next_url = reverse('posts:posts-content', kwargs={'pk': post_id})
            return redirect(reverse('posts:loginUser') + '?next=' + next_url + '&post_id=' + str(post_id))
        return super().handle_no_permission()

    model = Post

urls.py

app_name = 'posts'
urlpatterns = [
    path('', Index.as_view(), name='posts-index'),
    path('<int:pk>/', Content.as_view(), name='posts-content'),
    path('register/', register, name='register'),
    path('login/', loginUser, name='loginUser'),
    path('logout/', logoutUser, name='logoutUser'),
    path('profile/', profile, name='profile')
]

login.html

{% extends 'posts/base.html' %}
{% block title %}
   Sign Up
 {% endblock %}
 {% block content %}
<form action="{% url 'posts:loginUser' %}{% if next %}?next={{ next }}{% endif %}" method="post">
        {% csrf_token %}
        {{form}}
        <button type="submit">Login</button>
    </form>
{% endblock %}

已尝试的操作

我尝试打印next_url但始终得到None,也试过添加如下隐藏字段传递next参数,但问题仍未解决:

<form method="post" action="{% url 'posts:loginUser' %}" >
        {% csrf_token %}
        {{form}}
        <input type="hidden" name="next" value="{{next}}" />
        <button type="submit">Login</button>
    </form>

问题原因及修复方案

核心问题

  1. next参数未正确传递:登录页面渲染时,你没有把URL中的next参数传递给模板,导致模板里的{{ next }}是空值,不管是拼在表单action里还是用隐藏字段都无法传递到POST请求中;而且你的登录视图只从GET中取next,但表单是POST提交,GET参数不会自动保留。
  2. 自定义handle_no_permission画蛇添足:LoginRequiredMixin本身会自动将当前访问的URL作为next参数附加到登录URL后,不需要手动拼接,手动拼接还容易出现路径错误。

具体修复步骤

1. 修正loginUser视图,正确处理next参数

修改视图,同时从POST和GET中获取next,并将其传递给模板:

def loginUser(request):
    # 优先从POST取next,没有则从GET取
    next_url = request.POST.get('next', request.GET.get('next', None))
    if request.method == 'POST':
        form = Login(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                if next_url:
                    return HttpResponseRedirect(next_url)
                else:
                    return redirect('posts:posts-index')
    else:
        form = Login()
    # 将next_url传递给模板
    return render(request, 'posts/login.html', {'form': form, 'next': next_url})

2. 简化Content视图,移除自定义的handle_no_permission

直接使用LoginRequiredMixin的默认逻辑即可,它会自动处理未登录的重定向并附加next参数:

class Content(LoginRequiredMixin, DetailView):
    template_name = 'posts/post.html'
    context_object_name = 'post'
    # 使用命名URL,避免相对路径问题
    login_url = 'posts:loginUser'
    model = Post

3. 优化登录表单,用隐藏字段传递next

确保模板能接收到next变量,用隐藏字段传递更可靠:

{% extends 'posts/base.html' %}
{% block title %}
   Login
 {% endblock %}
 {% block content %}
<form method="post" action="{% url 'posts:loginUser' %}">
        {% csrf_token %}
        {{form}}
        {% if next %}
        <input type="hidden" name="next" value="{{ next }}" />
        {% endif %}
        <button type="submit">Login</button>
    </form>
{% endblock %}

额外建议

如果你是Django新手,推荐直接使用内置的django.contrib.auth.views.LoginView,它已经封装了next参数的处理、表单验证等逻辑,不需要自己写登录视图,能减少很多不必要的错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:05:19