什么是reverse()?

当我有时阅读Django代码时,我在一些模板中看到reverse()。我不太确定这是什么,但它与HttpResponseRedirect一起使用。reverse()应该如何以及何时被使用?

195496 次浏览

有个医生可以解决这个问题

https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls

它可以用来为给定的视图生成URL

主要的优点是您不必在代码中硬编码路由。

reverse() | Django文档 .


让我们假设在你的urls.py中你已经定义了这个:

url(r'^foo$', some_view, name='url_name'),

在模板中,你可以这样引用这个url:

<!-- django <= 1.4 -->
<a href="{% url url_name %}">link which calls some_view</a>


<!-- django >= 1.5 or with {% load url from future %} in your template -->
<a href="{% url 'url_name' %}">link which calls some_view</a>

这将被渲染为:

<a href="/foo/">link which calls some_view</a>

现在假设你想在你的views.py中做一些类似的事情——例如,你在其他一些视图(不是some_view)中处理一些其他URL(不是/foo/),你想将用户重定向到/foo/(通常是在成功提交表单时)。

你可以这样做:

return HttpResponseRedirect('/foo/')

但是,如果将来想更改URL该怎么办呢?你必须在你的代码中更新你的urls.py 而且对它的所有引用。这违反了DRY(不要重复)原则和只在一个地方编辑的整个思想——这是需要努力的。

相反,你可以说:

from django.http import HttpResponseRedirect
from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))

这将查看项目中定义的所有URL,以查找名称为url_name的URL,并返回实际的URL /foo/

这意味着你只能通过它的name属性来引用URL -如果你想改变URL本身或它引用的视图,你可以通过编辑一个地方来做到这一点- urls.py

reverse()用于坚持django的DRY原则,即如果你在未来改变url,那么你可以使用reverse(urlname)引用该url。

该函数支持干原则-确保你不硬编码url在你的应用程序。一个url应该定义在一个地方,只有一个地方-你的url配置。之后,你真的只是引用该信息。

使用reverse()来给你一个页面的url,给定视图的路径,或者url conf中的page_name参数。你可以在用{% url 'my-page' %}在模板中这样做没有意义的情况下使用它。

有很多地方可以使用这个功能。我发现我使用它的一个地方是在视图中重定向用户时(通常是在成功处理表单之后)

return HttpResponseRedirect(reverse('thanks-we-got-your-form-page'))

您也可以在编写模板标记时使用它。

另一次我使用reverse()是模型继承。我有一个父模型上的ListView,但想从这些父对象中的任何一个到它的相关子对象的DetailView。我附加了一个get__child_url()函数到父函数,它识别了子函数的存在,并使用reverse()返回它的DetailView的url。

这是一个老问题,但这里有一些东西可能会帮助到一些人。

官方文件显示:

Django提供了用于执行URL反转的工具 需要url的不同层:模板中:使用url 模板标签。在Python代码中:使用reverse()函数。在高等 与Django模型实例的url处理相关的级别代码 < / p > get_absolute_url()方法。

如。在模板中(url标签)

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>

如。python代码中(使用reverse函数)

return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

现有的答案在解释Django中reverse()函数的< em > < / em >方面做得很好。

然而,我希望我的回答能对< em > < / em >为什么有不同的理解:为什么在模板视图绑定中使用reverse()而不是其他更直接、更python化的方法,以及Django路由逻辑中“重定向通过 reverse()模式”流行的一些合理原因。

一个关键的好处是反向构造url,正如其他人提到的那样。就像你如何使用{% url "profile" profile.id %}从你的应用程序的url配置文件中生成url:例如path('<int:profile.id>/profile', views.profile, name="profile")

但正如OP所指出的,reverse()的使用通常也与HttpResponseRedirect的使用结合在一起。但是为什么呢?

我不太确定这是什么,但它与HttpResponseRedirect一起使用。如何以及何时应该使用这个reverse() ?

考虑下面的views.py:

from django.http import HttpResponseRedirect
from django.urls import reverse


def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected = question.choice_set.get(pk=request.POST['choice'])
except KeyError:
# handle exception
pass
else:
selected.votes += 1
selected.save()
return HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)
))

最小值urls.py:

from django.urls import path
from . import views


app_name = 'polls'
urlpatterns = [
path('<int:question_id>/results/', views.results, name='polls-results'),
path('<int:question_id>/vote/', views.vote, name='polls-vote')
]

vote()函数中,我们的else块中的代码以以下模式使用reverseHttpResponseRedirect:

HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)

这首先意味着我们不必硬编码URL(与DRY原则一致),但更重要的是,reverse()提供了一种优雅的方式来构造URL字符串,通过处理从参数中解压缩的值(args=(question.id)由URLConfig处理)。假设question有一个属性id,其中包含值5,那么从reverse()构造的URL将是:

'/polls/5/results/'

在普通的模板-视图绑定代码中,我们使用HttpResponse()render(),因为它们通常涉及较少的抽象:一个视图函数返回一个模板:

def index(request):
return render(request, 'polls/index.html')

但是在许多重定向的合法情况下,我们通常关心从参数列表构造URL。这些情况包括:

  • HTML表单通过POST请求提交
  • 验证后用户登录
  • 通过JSON web令牌重置密码

其中大多数涉及某种形式的重定向和通过一组参数构造的URL。希望这能增加已经有用的答案!

现有的答案非常清楚。以防你不知道为什么它被称为reverse:它接受一个url名称的输入,并给出实际的url,这与先有一个url,然后再给它一个名称相反。