有时当我阅读Django代码时,会看到一些模板reverse()
。我不太清楚这是什么,但是它与HttpResponseRedirect一起使用。reverse()
应该如何以及何时使用?
如果有人给出一些例子的答案是件好事...
有时当我阅读Django代码时,会看到一些模板reverse()
。我不太清楚这是什么,但是它与HttpResponseRedirect一起使用。reverse()
应该如何以及何时使用?
如果有人给出一些例子的答案是件好事...
Answers:
假设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
)中处理其他URL(不是),并且您想要将用户重定向到/foo/
(通常是成功提交表单时)。
您可以这样做:
return HttpResponseRedirect('/foo/')
但是,如果您以后想更改网址怎么办?您必须在代码中更新您urls.py
及其所有引用。这违反了DRY(请勿重复自己),即只编辑一个位置的整个想法,这是我们要努力的目标。
相反,您可以说:
from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))
这将在项目中定义的所有url中查找使用name定义的url url_name
并返回实际的url /foo/
。
这意味着您只能通过其name
属性来引用url- 如果要更改url本身或它所引用的视图,则只能通过编辑一个位置来进行此操作- urls.py
。
{{ url 'url_name' }}
应该{% url url_name %}
在Django 1.4或更早的版本中。这将在下一个Django版本(1.5)中更改,然后应为{% url 'url_name' %}
。如果您向下滚动到“前向兼容性”部分,则url templatetag的文档会提供一些很好的信息
url_reverse
。处理此类奇怪情况的最佳方法是拒绝使用它们。
这是一个古老的问题,但这可能会对某人有所帮助。
从官方文档:
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,)))
现有的答案在解释做了伟大的工作,什么 这个的reverse()
在Django功能。
但是,我希望我的答案能解释一个不同的原因:为什么reverse()
在模板视图绑定中使用其他更简单,可以说是更多python方式的方法,以及这种“ 通过 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
块中的代码reverse
与HttpResponseRedirect
以下模式一起使用:
HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)
首先,这意味着我们不必对URL进行硬编码(与DRY原理一致),但是更关键的是,reverse()
它提供了一种优雅的方式来构造URL字符串,方法args=(question.id)
是处理从参数解压缩的值(由URLConfig处理)。假设question
有一个id
包含value 的属性,5
则从构造的URL reverse()
将是:
'/polls/5/results/'
在普通的模板视图绑定代码中,我们使用HttpResponse()
或,render()
因为它们通常涉及较少的抽象:一个视图函数返回一个模板:
def index(request):
return render(request, 'polls/index.html')
但是在许多合法的重定向情况下,我们通常关心的是从参数列表中构造URL。这些情况包括:
POST
请求提交HTML表单其中大多数涉及某种形式的重定向,以及通过一组参数构造的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()
为父级附加了一个函数,该函数标识了子级的存在,并使用返回了其DetailView的url reverse()
。
有一个文档
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
它可以用于生成给定视图的URL
主要优点是您无需在代码中硬编码路由。
现有的答案很明确。以防万一,您不知道为什么要调用reverse
它:它接受一个URL名称的输入并给出实际的URL,这与首先拥有一个URL然后再给它一个名称相反。
url--> view name
。但是有时,例如在重定向时,您需要反向操作并为Django提供视图名称,然后Django会生成适当的url。换句话说,view name --> url
。也就是说,reverse()
(与url函数相反)。仅仅调用它似乎更透明,generateUrlFromViewName
但这太长了,可能还不够通用:docs.djangoproject.com/en/dev/topics/http/urls/…–