什么是Django中的reverse()

时间:2012-06-28 09:26:53

标签: django

当我有时阅读django代码时,我会看到一些模板reverse()。我不太清楚这是什么,但它与HttpResponseRedirect一起使用。应该如何以及何时使用reverse()

如果有人用一些例子给出答案,那就太好了......

7 个答案:

答案 0 :(得分:278)

reverse() | Django documentation


urls.py中定义:

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

在模板中,您可以将此网址称为:

<!-- 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中做类似的事情 - 例如您正在处理其他一些视图中的其他网址(不是/foo/)(而不是some_view),并且您希望将用户重定向到/foo/(通常是成功提交表单的情况)。< / p>

你可以这样做:

return HttpResponseRedirect('/foo/')

但是如果你想在将来更改网址怎么办?您必须在代码中更新urls.py 对它的所有引用。这违反了DRY (Don't Repeat Yourself),只是编辑一个地方的整个想法,这是值得努力的目标。

相反,你可以说:

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

查看项目中为名称为url_name定义的网址定义的所有网址,并返回实际网址/foo/

这意味着您只能通过其name属性引用网址 - 如果您想要更改网址本身或其引用的视图,您可以通过仅修改一个地点来实现此目的 - urls.py

答案 1 :(得分:7)

这是一个老问题,但这可能对某些人有所帮助。

来自官方文档:

  

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

EG。在模板(网址标签)

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

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

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

答案 2 :(得分:4)

有一个文档

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

它可用于生成给定视图的URL

主要优点是您不需要在代码中硬编码路径。

答案 3 :(得分:2)

该功能支持干燥原则 - 确保您不会在整个应用程序中硬编码网址。网址应该在一个地方定义,而且只能在一个地方定义 - 您的网址。之后你真的只是引用那个信息。

使用reverse()为您提供网页的网址,给定视图的路径或网址配置中的page_name参数。如果在使用{% url 'my-page' %}的模板中进行此操作没有意义,您可以使用它。

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

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

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

我使用reverse()的另一个时间是模型继承。我在父模型上有一个ListView,但是希望从这些父对象中的任何一个获得它与其关联的子对象的DetailView。我将一个get__child_url()函数附加到父项,该函数标识了子项的存在,并使用reverse()返回了它的详细信息视图的URL。

答案 4 :(得分:1)

reverse()用于遵循django DRY原则,即如果您将来更改URL,则可以使用reverse(urlname)引用该URL。

答案 5 :(得分:1)

现有答案非常清楚。万一您不知道为什么叫它reverse:它将输入一个URL名称并给出实际的URL,这与先拥有一个URL然后再给它一个名称相反。

答案 6 :(得分:0)

现有答案在解释Django中此reverse()函数的 什么 方面做得很好。

但是,我希望我的答案对 为什么 有所不同:为什么用reverse()代替其他更简单,可以说更多的东西模板视图绑定中的pythonic方法,以及这种“通过通过 reverse()模式重定向”在Django路由逻辑中流行的合理原因是什么。

一个关键的好处就是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。这些情况包括:

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

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