什么是Django中的reverse()
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是Django中的reverse()相关的知识,希望对你有一定的参考价值。
当我有时阅读django代码时,我会在一些模板中看到reverse()
。我不太清楚这是什么,但它与HttpResponseRedirect一起使用。如何以及何时使用reverse()
?
如果有人用一些例子给出答案,那就太好了......
https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse
在你的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/
(通常是成功提交表单的情况)
你可以这样做
return HttpResponseRedirect('/foo/')
但是如果你想在将来更改网址怎么办 - 你必须在你的代码中更新你的urls.py
及其所有引用。这违反了DRY(google it)。
相反,你可以说
from django.urls import reverse
return HttpResponseRedirect(reverse('url_name'))
这将查看项目中为名称为url_name
定义的url定义的所有URL,并返回实际的url /foo/
。
这意味着你只通过它的name
属性引用url - 如果你想要更改url本身或它引用的视图你可以通过仅编辑一个地方来做到这一点 - urls.py
。编辑一个地方的整个想法被称为“不要重复自己”,并且是值得努力的事情。
这是一个古老的问题,但这里可能有助于某些人。
来自官方文档:
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,)))
有一个文件
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
它可用于生成给定视图的URL
主要优点是您不需要在代码中硬编码路由。
该功能支持干燥原则 - 确保您不会在整个应用程序中硬编码网址。网址应该在一个地方定义,而且只能在一个地方定义 - 您的网址。之后你真的只是引用那些信息。
使用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。
reverse()用于遵循django DRY原则,即如果您将来更改URL,则可以使用reverse(urlname)引用该URL。
现有的答案很好地解释了Django中这个reverse()
功能的用途。
但是,我希望我的回答能够解释为什么:为什么在模板视图绑定中使用reverse()
代替其他更直接,可以说是更加pythonic的方法,以及这种“重定向”流行的正当理由是什么通过reverse()
模式“在Django路由逻辑中。
正如其他人所提到的,一个关键的好处是反向构建网址。就像你如何使用{% 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
,其中包含值5
,从reverse()
构造的URL将是:
'/polls/5/results/'
在普通的模板视图绑定代码中,我们使用HttpResponse()
或render()
,因为它们通常涉及较少的抽象:一个视图函数返回一个模板:
def index(request):
return render(request, 'polls/index.html')
但在许多合法的重定向情况下,我们通常关心从参数列表构造URL。这些包括如下情况:
- 通过
POST
请求提交HTML表单 - 用户登录后验证
- 通过JSON Web令牌重置密码
其中大多数涉及某种形式的重定向,以及通过一组参数构建的URL。希望这会增加已经有用的答案线程!
以上是关于什么是Django中的reverse()的主要内容,如果未能解决你的问题,请参考以下文章
Django 中的 login_required 装饰器和 urlresolver.reverse()