python web开发——Django URL路由

路由原理

当用户发出一个请求时(例如:在浏览器中输入一个url地址),Django会到系统中的urlpatterns列表中查找匹配的url,如果找到了,执行该url对应的视图,视图一般是一个函数,函数中带一个请求参数HTTPRequest。

每个模块都有自己的一个urlpatterns,Django只会查找项目下中的urls.py中查找,所以需要将各个模块中的urls.py包含到其中。

urlpatterns 语法

模块中的urlpatterns如下所示:

urlpatterns=[
    url(r'^$',views.index)
]

第一个参数是url的正则表达式,第二个参数是调用的视图函数

项目中的urlpatterns如下所示:

urlpatterns=[
    url(r'^admin/',admin.site.urls),
    #url(r'^app/',include('app.urls'))
    url(r'^$',include('app.urls'))
]

第一个参数是对应的模块,第二个参数是包含的url

更多正则实例

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^articles/2003/$',views.special_case_2003),
    url(r'^articles/([0-9]{4})/$',views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$',views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',views.article_detail),
]

注意

  • 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
  • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
  • 每个正则表达式前面的’r’ 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义。
一些请求的例子
  • /articles/2005/03/ 请求将匹配列表中的第三个模式。Django 将调用函数views.month_archive(request, ‘2005’, ‘03’)。
  • /articles/2005/3/ 不匹配任何URL 模式,因为列表中的第三个模式要求月份应该是两个数字。
  • /articles/2003/ 将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。请像这样自由插入一些特殊的情况来探测匹配的次序。
  • /articles/2003 不匹配任何一个模式,因为每个模式要求URL 以一个斜线结尾。
  • /articles/2003/03/03/ 将匹配最后一个模式。Django 将调用函数views.article_detail(request, ‘2003’, ‘03’, ‘03’)。
命名组

上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。

在Python 正则表达式中,命名正则表达式组的语法是(?Ppattern),其中name 是组的名称,pattern 是要匹配的模式。

下面是以上URLconf 使用命名组的重写:

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^articles/2003/$',views.special_case_2003),
    url(r'^articles/([0-9]{4})/$',views.year_archive),
    url(r'^articles/([0-9]{4})/(?P<month>[0-9]{2})/$',views.month_archive),
    url(r'^articles/([0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$',views.article_detail),
]

这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。例如:

  • /articles/2005/03/ 请求将调用views.month_archive(request, year=’2005’, month=’03’)函数,而不是views.month_archive(request, ‘2005’, ‘03’)。
  • /articles/2003/03/03/ 请求将调用函数views.article_detail(request, year=’2003’, month=’03’, day=’03’)。

在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;

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.urlresolvers.reverse() 函数。
  • 在更高层的与处理Django 模型实例相关的代码中:使用get_absolute_url() 方法。
例子

考虑下面的URLconf:

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

根据这里的设计,某一年nnnn对应的归档的URL是/articles/nnnn/。

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

<a href="{% url 'news-year-archive' 2018 %}">2018 Archive</a>

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

在Python 代码中,这样使用:

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect

def redirect_to_year(request):
    #...
    year = 2018
    #...
    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

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

在某些场景中,一个视图是通用的,所以在URL 和视图之间存在多对一的关系。对于这些情况,当反查URL 时,只有视图的名字还不够。请阅读下一节来了解Django 为这个问题提供的解决办法。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值