当我有时阅读 Django 代码时,我会在一些模板中看到 reverse()
。我不太确定这是什么,但它与 HttpResponseRedirect 一起使用。这个 reverse()
应该如何以及何时使用?
url--> view name
。但有时,比如重定向时,你需要反方向走,给 Django 一个视图的名称,Django 会生成相应的 url。换句话说,view name --> url
。即 reverse()
(与 url 函数相反)。将其称为 generateUrlFromViewName
似乎更透明,但这太长而且可能不够通用:docs.djangoproject.com/en/dev/topics/http/urls/…
reverse()
| Django documentation
假设您在 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 (Don't Repeat Yourself) 原则和仅在一个地方进行编辑的整个想法 - 这是值得努力的事情。
相反,你可以说:
from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))
这会在您的项目中定义的所有 URL 中查找以名称 url_name
定义的 URL,并返回实际的 URL /foo/
。
这意味着您仅通过其 name
属性来引用 URL - 如果您想要更改 URL 本身或它所引用的视图,您可以通过仅编辑一个位置来执行此操作 - urls.py
。
现有的答案很清楚。以防万一您不知道为什么将其称为 reverse
:它需要输入一个 url 名称并给出实际的 url,这与先有一个 url 然后给它一个名称相反。
现有答案很好地解释了 Django 中这个 reverse()
函数的什么。
但是,我希望我的回答能对 why 有不同的看法:为什么在模板中使用 reverse()
代替其他更直接、可以说更 Python 的方法 -视图绑定,以及这种“重定向 via 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()
提供了一种通过处理从参数中解包的值来构造 URL 字符串的优雅方式(处理 args=(question.id)
通过 URLConfig)。假设 question
具有包含值 5
的属性 id
,则从 reverse()
构造的 URL 将是:
'/polls/5/results/'
在普通的模板视图绑定代码中,我们使用 HttpResponse()
或 render()
,因为它们通常涉及较少的抽象:一个视图函数返回一个模板:
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()
返回了它的 DetailView 的 url。
有一个文档
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
它可用于为给定视图生成 URL
主要优点是您不会在代码中对路由进行硬编码。
reverse()
用于遵守 django DRY 原则,即如果您将来更改 url,那么您可以使用 reverse(urlname) 引用该 url。
不定期副业成功案例分享
{{ url 'url_name' }}
应该是{% url url_name %}
。这将在下一个 Django 版本 (1.5) 中更改,然后应该是{% url 'url_name' %}
。如果您向下滚动到“向前兼容性”部分,url templatetag 的文档会提供一些很好的信息{% %}
而不是可变标签{{ }}
用于 url 标签 :)url_reverse
的需求。处理这些怪事的最好方法是拒绝使用它们。