Django 2.0:路径转换器(Path converter)的用法
Django2.0 于 2017 年 12 月 2 日已经正式发布。Django2.0 支持 Python3.4,3.5 以及 3.6,移除了对 Python2.7 的支持。官方强烈建议 Python 3.x 使用最新的版本。
在 Django2.0 其中一个新特性为:简化 Url 路由的语法。
在代码上主要体现在新增了 django.urls.path 函数,它带来了更简洁、更可读的路由语法,如:
原来的 url
url(r'^articles/(?P<year>[0-9]{4})//div>, views.year_archive),
Django2.0 新语法
path('articles/<int:year>/', views.year_archive),
新语法支持 url 参数的类型转化。例子里的 year_archive 函数接收到的 year 参数作为参数,并且会自动转换 year 为整型而不是字符串。
在 Django1.x 里,我们需要对 year 做类型转换:
def year_archive(request, year):
year = int(year)
URL 参数捕获
在新的语法里,url 字符串有以下规则:
- 在 url 里使用尖括号“<>”来捕获值
- 尖括号捕获值的格式。其中 converter 为路径转换器,name 为参数名,如。对于捕获的值没有路径转换器,那么它会匹配除了斜杠"/"外的所有字符作为捕获的值。
- url 不需要以斜杠开头。
代码示例
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:slug>/', views.article_detail),
]
匹配示例
- /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”)
Path Converter
url 里捕获的值使用 Path Converter 来对值做转换,如类型转换。Django2.0 自带了默人的 Path Converter,同时也支持自定义 Path Conveter。
默认 Path converter
Django2.0 自带的 PathConveter 包括:
- str:匹配除了路径分隔符(/)之外的非空字符串,如果没有转换器,默认使用 str 作为转换器。
- int:匹配 0 及正整数。
- slug:匹配字母、数字以及横杠、下划线组成的字符串。
- uuid:匹配格式化的 uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
- path:匹配任何非空字符串,包含了路径分隔符(/)
注册自定义 Path Converter
当默认的 Path Converter 不能满足需求时,Django2.0 支持用户注册自定义的 Path Converter。
Path Converter 是一个类,定义 Converter 类需要包含下面的属性或方法:
- regex 属性,字符串类型
- to_python(self, value) 方法,它处理将匹配的字符串转换为应该传递给 view 函数的类型。 如果它不能转换给定的值,它应该抛出 ValueError。
- to_url(self, value) 方法,和 to_python 相反,它会将 Python 类型转换为在 URL 中使用的字符串。
示例
定义 Path Converter
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
使用 register_converter()注册 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),
...
]
正则表达式匹配
Django2.0 也支持我们使用正则表达式来捕获值。注意,用正则表达式捕获值,需要使用 re_path(),而不是前面介绍的 path()。
正则表达式建议使用命名正则表达式组,语法如下:
(?P<name>pattern)
其中,尖括号里的 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>[\w-_]+)/', views.article_detail),
]
与前面的示例不同点:
- 这里的代码匹配更加严格,比如 year 为 10000 就无法匹配,因为它超出了正则规定的 4 位数
- 传给 view 函数的参数为字符串类型,这点和 Django 使用 url 是一样的。
设置默认值
在 path 里支持对 view 设置默认值。
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page),
]
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...
page 函数 num 的默认值设置为 1.
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于