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>
问题原因及修复方案
核心问题
next参数未正确传递:登录页面渲染时,你没有把URL中的next参数传递给模板,导致模板里的{{ next }}是空值,不管是拼在表单action里还是用隐藏字段都无法传递到POST请求中;而且你的登录视图只从GET中取next,但表单是POST提交,GET参数不会自动保留。- 自定义
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
相关产品推荐
相关产品推荐

