Django中URL的next参数打印正常但重定向时无法显示问题排查
问题:Django注册视图中next参数打印正常但重定向时URL不显示该参数?
我写了如下的Django注册视图代码:
def signup(request): next = request.GET.get('next', '') print(next) if request.user.is_authenticated: return redirect('/') else: if request.method == "POST": first_name=request.POST['first_name'] email=request.POST['email'] password=request.POST['password'] cpassword=request.POST['cpassword'] signup_uri = f'/signup?next={next}' if password==cpassword: if User.objects.filter(email=email).exists(): messages.info(request,'Email already in use') return redirect(signup_uri) elif User.objects.filter(mobile=mobile).exists(): messages.info(request,'Mobile Number already in use') return redirect(signup_uri) else: user=User.objects.create_user(first_name=first_name,email=email,password=password) user.save(); return redirect(f'/login?next={next}') else: messages.info(request,'Passwords not matching') return redirect('signup_uri') else: return render(request,'signup.html')
遇到的问题:在函数开头打印next参数时显示正常,但重定向到/signup?next={next}或/login?next={next}时,URL里的next是空的。请问可能是什么原因?
解决方案
我帮你排查出两个关键问题,逐个解决就能修复:
1. 错误地将变量名作为字符串传递给redirect()
看你代码里的密码不匹配分支:
else: messages.info(request,'Passwords not matching') return redirect('signup_uri')
这里你把signup_uri用引号括起来了,Django会把它当作URLconf中定义的URL名称去查找,而不是使用你之前拼接好的带next参数的URL变量。正确写法应该去掉引号,直接传递变量:
return redirect(signup_uri)
2. POST请求时丢失了next参数
你当前只从request.GET中获取next,但用户提交表单(POST请求)时,原来的GET参数不会自动携带到POST请求里,这时候request.GET.get('next')就会是空值,导致后续拼接的URL里next为空。
解决方法分两步:
第一步:在signup.html的表单中添加隐藏字段
把当前页面的next参数通过隐藏字段传递到POST请求里:
<form method="POST"> {% csrf_token %} <!-- 你的其他表单字段 --> <input type="hidden" name="next" value="{{ request.GET.next }}"> <button type="submit">注册</button> </form>
第二步:修改视图中获取next的逻辑
同时从GET和POST中获取next,确保POST请求时也能拿到参数:
def signup(request): # 兼顾GET和POST请求中的next参数 next = request.GET.get('next', '') or request.POST.get('next', '') print(next) # ... 后续代码保持不变
额外小提醒
- 尽量避免直接硬编码URL(比如
redirect('/')、/signup?next={next}),建议使用Django的reverse()函数或者URL名称生成URL,后续修改URL结构时不用到处改代码。 - 你的代码里用到了
mobile字段,但在POST请求中没有写mobile=request.POST['mobile'],运行时会报错,记得补上这行代码。
内容的提问来源于stack exchange,提问作者VATSAL JAIN
相关产品推荐
相关产品推荐

