Django基础之命名URL和URL反向解析

在使用Django项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。

人们强烈希望不要硬编码这些URL(费力,不可扩展且容易产生错误)或者设计一种与URLconf毫不相干的专门的URL生成机制,因为这样容易导致一定程度上产生过期的URL。

换句话讲,需要的是一个DRY机制。除了其它有点,它还允许设计的URL可以自动更新而不用遍历项目的源代码来搜索并替换过期的URL。

获取一个URL最开始想到的信息是处理它视图的标识,查找正确的URL的其他必要的信息有视图参数的类型(位置参数,关键字参数)和值。

Django提供一个办法是让URL映射到URL设计唯一的地方。

你填充你的URLconf,然后可以双向使用它:

  • 根据用户/浏览器发起的URL请求,它调用正确的Django视图,并从URL中提取它的参数需要的值。
  • 根据Django视图的标识和将要传递给它的参数的值,获取与之关联的URL。

第二种方式叫做反向解析URL、反向URL匹配、反向URL查询或简单的URL反查。

在需要URL的地方,对于不同层级,Django提供不同的工具用于URL反查

  • 在模板中:使用url模板标签
  • 在Python代码中:使用django.core.urlesolvers.reverse()函数
  • 在更高层的与处理Django模型实例相关的代码中:使用get_absolute_url()方法

简单来说,就是可以给我们的URL匹配规则起个名字,一个URL匹配模式起一个名字。

这样我们以后就不需要写死URL代码了,只需要通过名字来调用当前的URL。

比如:

url(r"^home", views.home, name="home"),        #给自己的url匹配模式起名为home
url(r"^index/(\d*)", views.index, name="index")#给自己的url匹配模式起名为index

 

这样,在模板里面可以这样引用:

{% url "home" %}

在views函数中可以这样引用:

from django.urls import reverse
reverse("index", args=("2018", ))

示例,看下面的URLconf:

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r"^articles/([0-9]{4})/$", views.year_archive, name="new-year-archive")
]

根据上面代码的设计,某一年nnnn对应的归档的URL是/articles/nnnn

你可以在模板的代码中使用下面的方法获得它们:

<a href="{% url "news-year-archive" 2012 %}">2012 Archive</a>
<ul>
{% for yearvar in year_list%}
<li>
<a href="{% ulr "news-year-archive" yearvar%}">{{ yearvar }} Archive</a>
</li>
{% endfor %}
</ul>

 

在Python代码中,这么使用:

from django.urls import reverse
from django.shortcuts import redirect
 
def redirect_to_year(request):
    year = 2006
    return redirect(reverse("news-year-archive", args=(year, )))

 

如果出于某种原因决定按年归档文章的URL应该调整一下,那么你将只需要修改URLconf中的内容。

在某些场景中,一个视图是通用的,所以在URL和视图之间存在多对一的关系。

对于这些情况,当反查URL时,只有视图的名字还不够。

注意:

为了完成上面例子中的URL反查,你将需要使用命名的URL模式。

URL名称使用的字符串可以包含任意字符,不只限制在合法的Python名称。

当你命名你的url模式时,请确保使用的名称不会与其它应用中名称冲突。如果你的URL模式叫做【comment】,而另外一个应用中也有一个同样的名称,当你在模板中使用这个名称的时候不能保证将插入哪个URL。

在URL名称中加上一个前缀,比如应用的名称,将减少冲突的可能。例如采用【myapp-comment】,而不是一个【comment】。

发表评论