django2:路由path语法

9月23,Django 发布了2.0a1版本,这是一个 feature freeze 版本,如果没有什么意外的话,2.0正式版不会再增加新的功能了。按照以往的规律,预计正式版将在12月发布。
备注:Django 2.0 于12月2日已经正式发布。 (链接)
2.0无疑是一个里程碑版本,移除了对 Python2.7 的支持,最少需要 3.4 以上,建议使用3.5以上的版本。
What’s new in Django2.0 文档中一共列出了三个新的特性:
- 更简单的URL路由语法 (Simplified URL routing syntax)
- admin应用的针对移动设备的优化改进(Mobile-friendly
contrib.admin) - 支持SQL开窗表达式(Window expressions)
第一个特性,主要用于动态路由定义上。在Django2.0代码实现中,主要的变化是新增了 django.urls.path 函数,它允许使用一种更加简洁、可读的路由语法。比如之前的版本的代码:
url(r'^articles/(?P[0-9]{4})/$', views.year_archive),
在新版本中也可以写为:
path('articles//', views.year_archive),
新语法支持类型转化,在上述的例子中, year_archive 函数接收到的year参数就变成整数而不是字符串。
如果你有接触过 Flask 框架,就会发现和 Variable-Rules 的语法形式和功能都是相类似的。
1.问题引入
下面是 Django1.X 的一段代码:
from django.conf.urls import url
def year_archive(request, year):
year = int(year) # convert str to int
# Get articles from database
def detail_view(request, article_id):
pass
def edit_view(request, article_id):
pass
def delete_view(request, article_id):
pass
urlpatterns = [
url('articles/(?P<year>[0-9]{4})/', year_archive),
url('article/(?P<article_id>[a-zA-Z0-9]+)/detail/', detail_view),
url('articles/(?P<article_id>[a-zA-Z0-9]+)/edit/', edit_view),
url('articles/(?P<article_id>[a-zA-Z0-9]+)/delete/', delete_view),
]
考虑下这样的两个问题:
第一个问题,函数 year_archive 中year参数是字符串类型的,因此需要先转化为整数类型的变量值,当然 year=int(year) 不会有诸如如TypeError或者ValueError的异常。那么有没有一种方法,在url中,使得这一转化步骤可以由Django自动完成?
第二个问题,三个路由中 article_id 在业务中表示同一个字段,使用同样的正则表达式,但是你需要写三遍,当之后 article_id 规则改变后,需要同时修改三处代码,那么有没有一种方法,只需修改一处即可?
在 Django2.0 中,可以使用 path 解决以上的两个问题。
2.使用示例
这是一个简单的例子:
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug>/', views.article_detail),
]
基本规则:
- 使用尖括号(
<>)从url中捕获值。 - 捕获值中可以包含一个转化器类型(converter type),比如使用 `` 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了
/字符。 - 无需添加前导斜杠。
以下是根据 2.0官方文档 而整理的示例分析表:
| 请求URL | 匹配项 | 视图函数调用形式 |
|---|---|---|
| /articles/2005/03/ | 第3个 | views.month_archive(request, year=2005, month=3) |
| /articles/2003/ | 第1个 | views.special_case_2003(request) |
| /articles/2003 | 无 | - |
| /articles/2003/03/building-a-django-site/ | 第4个 | views.article_detail(request, year=2003, month=3, slug=”building-a-django-site”) |
3.path转化器
文档原文是Path converters,暂且翻译为转化器。
Django默认支持以下5个转化器:
- str,匹配除了路径分隔符(
/)之外的非空字符串,这是默认的形式 - int,匹配正整数,包含0。
- slug,匹配字母、数字以及横杠、下划线组成的字符串。
- uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
- path,匹配任何非空字符串,包含了路径分隔符
4.自定义转化器
4.1 定义
对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:
regex类属性,字符串类型to_python(self, value)方法,value是由类属性regex所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。to_url(self, value)方法,和to_python相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。
先看看默认的 IntConverter 和 StringConverter 是怎么实现的:
class IntConverter:
regex = '[0-9]+'
def to_python(self, value):
return int(value)
def to_url(self, value):
return str(value)
class StringConverter:
regex = '[^/]+'
def to_python(self, value):
return value
def to_url(self, value):
return value
第二个例子,是自己实现的4位年份的转化器。
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
4.2 注册
使用register_converter 将其注册到URL配置中:
from django.urls import register_converter, path
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]
5.使用正则表达式
如果上述的paths和converters还是无法满足需求,也可以使用正则表达式,这时应当使用 django.urls.re_path函数。
在Python正则表达式中,命名式分组语法为 (?Ppattern) ,其中name为名称, pattern为待匹配的模式。
之前的示例代码也可以写为:
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path('articles/(?P<year>[0-9]{4})/', views.year_archive),
re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/', views.month_archive),
re_path('articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[^/]+)/', views.article_detail),
]
这段代码和之前的代码实现了基本的功能,但是还是有一些区别:
- 这里的代码匹配更加严格,比如year=10000在这里就无法匹配。
- 传递给视图函数的变量都是字符串类型,这点和
url是一致的。
无命名分组
一般来说,不建议使用这种方式,因为有可能引入歧义,甚至错误。
6.Import变动
django.urls.path 可以看成是 django.conf.urls.url 的增强形式。
为了方便,其引用路径也有所变化,请注意下 urls 包路径的变更,不再是 conf 的子包了,目前和 views 、conf 一样,被认为是 Django 的核心组件。
| 1.X | 2.0 | 备注 |
|---|---|---|
| - | django.urls.path | 新增,url的增强版 |
| django.conf.urls.include | django.urls.include | 路径变更 |
| django.conf.urls.url | django.urls.re_path | 异名同功能,url不会立即废弃 |
7.代码改写
将“问题引入”一节的代码使用新的path函数可以改写如下:
from django.urls import path, register_converter
from django.urls.converters import SlugConverter
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
register_converter(SlugConverter, 'article_id')
register_converter(FourDigitYearConverter, 'year')
def year_archive(request, year):
print(type(year)) # <class 'int'>
# Get articles from database
def detail_view(request, article_id):
pass
def edit_view(request, article_id):
pass
def delete_view(request, article_id):
pass
urlpatterns = [
path('articles/<year:year>/', year_archive),
path('article/<article_id:article_id>/detail/', detail_view),
path('articles/<article_id:article_id>/edit/', edit_view),
path('articles/<article_id:article_id>/delete/', delete_view),
]
8.总结
第一,目前 路由(url)到视图(View)的流程可以概括为四个步骤:
- url匹配
- 正则捕获
- 变量类型转化
- 视图调用
Django2.0 和之前相比多了 变量类型转化 这一步骤。
第二,新的path语法可以解决一下以下几个场景:
- 类型自动转化
- 公用正则表达式
django2:路由path语法的更多相关文章
- django2笔记:路由path语法
django2笔记:路由path语法 9月23,Django 发布了2.0a1版本,这是一个 feature freeze 版本,如果没有什么意外的话,2.0正式版不会再增加新的功能了.按照以往的规律 ...
- 路由跟踪语法:tracert www.love125.com
tracert www.love125.com 路由跟踪语法
- Django2.0中得url路由path得用法
Django2.0中,url得匹配规则更新了,在django1.0中,url是用正则表达式书写得,相对来说比较繁琐一些,在django2.0中进行了升级优化,改为了path from django.u ...
- Django2.0 path和re_path使用
Django2.0发布后,很多人都拥抱变化,加入了2的行列.但是和1.11相比,2.0在url的使用方面发生了很大的变化,下面介绍一下: 一.实例 先看一个例子: from django.urls i ...
- Django-2 路由层
U RL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表. 2.1 简单的路由配置 from django.urls import p ...
- vue路由高级语法糖
1.当 <router-link> 对应的路由匹配成功,将自动设置 class 属性值 .router-link-active. 模板中可以用{{$route.params.xxx取到路由 ...
- angularjs路由path方式实现原理探究
angularjs路由 https://angular.io/guide/router 通过URL解释, 来定位客户端生成的浏览器端视图. 你可绑定路由到页面的链接上, 当用户点击链接, 可以浏览到相 ...
- wpf path语法
http://www.cnblogs.com/HQFZ/p/4452548.html WPF系列 Path表示语法详解(Path之Data属性语法)
- 使用Path语法取得对象的值
借鉴了http://stackoverflow.com/questions/4473928/c-sharp-dynamic-string-property-path public class ...
随机推荐
- 使用Nginx搭建Tomcat9集群,Redis实现Session共享
使用Nginx搭建Tomcat9集群,Redis实现Session共享 1.tomcat准备 首先准备两个tomcat9 ,修改配置文件server.xml 如果在多个服务器上分别启动tomcat 则 ...
- 四十六、SAP的Message中E和W区别
一.如果写的是E,则报红色的信息,如图 效果如下 二.如果是写的是W,则报黄色的信息 效果如下
- [题解] LuoguP4609 [FJOI2016]建筑师
传送门 首先对于高度为\(n\)的建筑,他的左边有\(A-1\)个建筑能被看到,右边有\(B-1\)个建筑能被看到,这两者类似,所以先来看左边. 一个建筑将会遮挡住它后面的高度比它矮的建筑,直到一个高 ...
- 11 数据存储(Unity3D)
所有的游戏开发都离不开数据存储的操作,Unity3D也不例外PlayerPrefs:PlayerPrefs是Unity系统自带的的一种最简单的存储方式,数据是使用字典的方法来存储的 PlayerPre ...
- MacOS通过ssh连接基于Virtualbox的Ubuntu虚拟机
以前总是用Windows软件putty进行ssh连接,今天尝试使用macos. 实验环境:主机:macos 10.15.3 客户机:Ubuntu 18.04 默认情况下,Ubuntu没有安装SSH,需 ...
- 基于Ambari Server部署HDP集群实战案例
基于Ambari Server部署HDP集群实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.部署Ambari Server端 博主推荐阅读: https://www.c ...
- Codeforces 392 B Blown Garland
题意:输入是由连续的RYGB和字符!组成的字符串,R代表红灯,Y代表黄灯,G代表绿灯,B代表蓝灯.简而言之,就是给定的字符串保证了下标对4取余相同的灯颜色都相同,但是有的地方为‘!’代表这个灯坏了,然 ...
- 每天一点点之vue框架开发 - vue-router路由进阶(路由别名、跳转、默认路由、二级路由、路由守卫)
路由别名 在main.js中的路由中添加name来创建别名 const routes = [ {path:'/footer',name:footerLink,component:Footer} ] ...
- JS最新最细面试题
转之:https://www.jianshu.com/p/f1f39d5b2a2e 1. javascript的typeof返回哪些数据类型. 答案:string,boolean,number,und ...
- 安装swoole redis异步 hiredis swoole扩展加载失败 或者不显示问题 解决办法
当前办法仅供参考 贴上报错 找了好久 根据网上办法也试了 没解决 最后 仔细读问题 觉得可能是 hiredis路径问题 终于解决了 解决办法: 进入你的安装包目录然后执行下面 mkdir /usr/l ...