当我有时阅读 Django 代码时,我会在一些模板中看到reverse()
。我不太确定这是什么,但它与 HttpResponseRedirect 一起使用。reverse()
这应该如何以及何时使用?
7 回答
让我们假设在您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
- 例如,您正在处理其他一些 URL(not /foo/
)在其他一些视图(not some_view
)中,并且您希望将用户重定向到/foo/
(通常是成功提交表单的情况)。
你可以这样做:
return HttpResponseRedirect('/foo/')
但是,如果您将来想更改 URL 怎么办?您必须在代码中更新您urls.py
和所有对它的引用。这违反了DRY(不要重复自己)原则和仅在一个地方进行编辑的整个想法——这是值得努力的事情。
相反,你可以说:
from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))
这会在您的项目中定义的所有 URL 中查找使用名称定义的 URL,url_name
并返回实际的 URL /foo/
。
这意味着您仅通过其name
属性引用 URL - 如果您想更改 URL 本身或它所引用的视图,您可以通过仅编辑一个位置来执行此操作 - urls.py
。
现有的答案很清楚。以防万一您不知道为什么调用reverse
它:它需要输入一个 url 名称并给出实际的 url,这与先有一个 url 然后给它一个名称相反。
现有的答案很好地解释了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
块中的代码使用reverse
了HttpResponseRedirect
以下模式:
HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)
这首先意味着我们不必对 URL 进行硬编码(符合 DRY 原则),但更重要的是,reverse()
通过处理从参数中解包的值(args=(question.id)
由 URLConfig 处理)提供了一种构造 URL 字符串的优雅方法。假设有一个包含 valuequestion
的属性,则从 构造的 URL将是:id
5
reverse()
'/polls/5/results/'
在普通的模板视图绑定代码中,我们使用HttpResponse()
orrender()
因为它们通常涉及较少的抽象:一个视图函数返回一个模板:
def index(request):
return render(request, 'polls/index.html')
但在许多合法的重定向案例中,我们通常关心从参数列表构造 URL。这些包括以下情况:
POST
通过请求提交 HTML 表单- 用户登录后验证
- 通过 JSON Web 令牌重置密码
其中大多数涉及某种形式的重定向,以及通过一组参数构造的 URL。希望这增加了已经有帮助的答案线程!
这是一个老问题,但这里有一些可能对某人有帮助的东西。
来自官方文档:
Django 提供了用于执行 URL 反转的工具,这些工具与需要 URL 的不同层相匹配: 在模板中:使用 url 模板标签。在 Python 代码中:使用 reverse() 函数。在与处理 Django 模型实例的 URL 相关的更高级别代码中: get_absolute_url() 方法。
例如。在模板中(url 标签)
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
例如。在python代码中(使用reverse
函数)
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
该函数支持干原则 - 确保您不会在整个应用程序中对 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()
函数,该函数标识了一个子级的存在,并使用reverse()
.
有一个文档
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
它可用于为给定视图生成 URL
主要优点是您不会在代码中对路由进行硬编码。
reverse()
用于遵守 django DRY 原则,即如果您将来更改 url,那么您可以使用 reverse(urlname) 引用该 url 。