反向后 Django 不显示正确的 URL

Django not displaying correct URL after reverse

有很多关于 Django 和 reverse() 方法的文档。我似乎无法找到我的确切问题。假设我有两个这样的 urlconf:

url(r'ParentLists/$', main_page, name = "main_page"),
url(r'ParentLists/(?P<grade_level>.+)/$', foo, name = "foo")

和两个对应的视图是这样的:

def main_page(request):

    if request.method == 'POST':
        grade_level = request.POST['grade_picked']
        return HttpResponseRedirect(reverse('foo', args = (grade_level,)))

    else:
        return render(request, 'index.html', context = {'grade_list' : grade_list})

def foo(request, grade_level):

    grade_level = request.POST['grade_picked']

    parent_list = # get stuff from database
    emails      = # get stuff from database

    return render(request, 'list.html', context = {'grade_list' : grade_list, 'parent_list' : parent_list}) 

这里,list.html 只是扩展了我的基本模板 index.html,其中包含一个带有年级的下拉框。当用户转到 /ParentLists 时,main_page 视图会按应有的下拉框呈现 index.html。

当用户从下拉框中选择一个年级(比如 5 年级)时,模板会提交表单,然后 main_page 再次执行 - 但这次是 POST 分支运行并且 HttpResponseRedirect 将用户带到 /ParentLists/05。这只会导致与 5 年级相关的 HTML table 显示在下拉框下方。

问题是,当用户现在选择说 10 年级时,table 更新为显示 10 年级的内容,但显示的 URL 仍然是 /ParentLists/05。我希望它是 /ParentLists/10.

显然,在第一次选择之后,main_page 视图再也不会执行。只有 foo 会...所以 HttpResponseRedirect 永远不会被调用。我应该如何重新组织它以获得我正在寻找的东西?提前致谢!

我建议您使用 kwargs 而不是 args。 视图的正确使用方法是:

your_url = reverse("<view_name>", kwargs={"<key>": "<value>"})

例如:

return HttpResponseRedirect(reverse('foo', kwargs={"grade_level": grade_level}))

此外,您正在使用 URL 而不是 POST 值将 "grade_level" 发送到您的视图 foo。我会删除该行:

grade_level = request.POST['grade_picked']

因为您将覆盖从 url 发送到方法的 grade_level。

正如您正确提到的那样,您永远不会从 foo() 重定向到 foo()。

所以解决这个问题的简单方法就是添加与 main_page() 视图类似的代码:

def foo(request, grade_level):

    if request.method == 'POST':
        grade_level = request.POST['grade_picked']
        return HttpResponseRedirect(reverse('foo', args = (grade_level,)))
    else:
        parent_list = # get stuff from database
        emails      = # get stuff from database

        return render(request, 'list.html', context = {'grade_list' : grade_list, 'parent_list' : parent_list})

请注意,我删除了 grade_level = request.POST['grade_picked'],因为正如 Nagkumar Arkalgud 正确所说的那样,它过分了。

此外,您可以使用快捷方式 redirect 而不是 HttpResponseRedirectreverse 的组合,这可能不太容易编码:

from django.shortcuts redirect
...
return redirect('foo', grade_level=grade_level)