什么是Django中的reverse()

lak*_*esh 190 django

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

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

scy*_*ale 301

https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse

在你的reverse()定义中:

url(r'^foo$', some_view, name='url_name'),
Run Code Online (Sandbox Code Playgroud)

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

<!-- 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>
Run Code Online (Sandbox Code Playgroud)

这将呈现为

<a href="/foo/">link which calls some_view</a>
Run Code Online (Sandbox Code Playgroud)

现在说你想在你的事情上做类似的事情urls.py- 例如你在其他views.py一些视图中处理其他网址(不是),/foo/而你想要将用户重定向到some_view(通常是成功提交表单的情况)

你可以这样做

return HttpResponseRedirect('/foo/')
Run Code Online (Sandbox Code Playgroud)

但是如果你想在将来更改网址怎么办 - 你必须在代码中更新你/foo/ 它的所有引用.这违反了DRY(google it).

相反,你可以说

from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))
Run Code Online (Sandbox Code Playgroud)

这将查看项目中为名称定义的url定义的所有URL,urls.py并返回实际的url url_name.

这意味着您只能通过其/foo/属性引用网址- 如果您想要更改网址本身或其引用的视图,您可以通过仅编辑一个地方来实现此目的name.编辑一个地方的整个想法被称为"不要重复自己",并且是值得努力的事情.

  • 仅供参考,在 Django 1.4 或更早版本中,`{{ url 'url_name' }}` 应该是 `{% url url_name %}`。这将在下一个 Django 版本(1.5)中改变,然后应该是`{% url 'url_name' %}`。如果您向下滚动到“向前兼容性”部分,[url templatetag](https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#url) 的文档会提供一些很好的信息 (4认同)
  • j_syk 谢谢 - 自从 1.3 发布以来,我一直在做 @load url from future@ ,但忘记了它还不是默认的。我会更新我的答案,以免让没有经验的人绊倒。 (2认同)
  • 已修复 - 我认为您自己编辑其他人答案中的愚蠢拼写错误被认为是完全可以接受的,所以如果您看到更多,请跳进去:-) (2认同)
  • 在这个网站上可以找到的最微妙的答案之一. (2认同)
  • "&gt;&gt;&gt;但是如果您将来想更改 url 该怎么办”,这些微妙之处在 0.0001% 的情况下很有用,解决方案就像一个有用的功能一样提供,人们使用它就好像他们是 '最佳实践”并留下混乱。说实话,如果将来更改 url 时,您只需执行全局查找替换即可。即使这个解决方案(使用 url_name)也容易出现“如果将来想更改 url_name 怎么办?”的问题。在 Django 中编码已超过 5 年,但尚未满足“url_reverse”的需求。处理这些奇怪现象的最好方法就是拒绝使用它们。 (2认同)

onl*_*tom 13

现有的答案在解释做了伟大的工作,什么 这个的reverse()在Django功能。

但是,我希望我的回答对原因有所不同:为什么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)
        ))
Run Code Online (Sandbox Code Playgroud)

而我们的最小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')
]
Run Code Online (Sandbox Code Playgroud)

vote()功能,在我们的代码else块使用reverse连同HttpResponseRedirect下面的模式:

HttpResponseRedirect(reverse('polls:polls-results',
                                        args=(question.id)
Run Code Online (Sandbox Code Playgroud)

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

'/polls/5/results/'
Run Code Online (Sandbox Code Playgroud)

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

def index(request):
    return render(request, 'polls/index.html') 
Run Code Online (Sandbox Code Playgroud)

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

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

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


yyF*_*red 10

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

  • 刚刚通过教程(Django Girls)学习 Django。这是一个陡峭的学习曲线。我认为这个函数的名字很可怕:没有任何限定的“reserve”非常强烈地建议保留一个列表或字符串,这显然与它没有任何关系。 (4认同)
  • @mikerodent 我完全同意你的观点。此外,这些答案都没有解释为什么该函数被称为反向函数。在我看来,这是一个很糟糕的名字。 (2认同)

Kis*_*vas 9

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

来自官方文档:

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

例如.在模板中(url标签)

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
Run Code Online (Sandbox Code Playgroud)

例如.在python代码中(使用该reverse函数)

return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
Run Code Online (Sandbox Code Playgroud)

  • 需要完整的描述老板 (3认同)

小智 5

该函数支持干燥原则 - 确保您不会在整个应用程序中对 URL 进行硬编码。url 应该定义在一处,并且只能定义在一个地方 - 你的 url conf。之后您实际上只是引用该信息。

用于reverse()为您提供页面的 url,给定视图的路径或 url conf 中的 page_name 参数。如果在模板中使用{% url 'my-page' %}.

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

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

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

我使用的另一次reverse()是模型继承。我在父模型上有一个 ListView,但想要从这些父对象中的任何一个获取其关联子对象的 DetailView。我将一个get__child_url()函数附加到父级,该函数识别子级的存在并使用 .return 返回其 DetailView 的 url reverse()