9月23,Django 发布了2.0a1版本,这是一个 feature freeze 版本,若是没有什么意外的话,2.0正式版不会再增长新的功能了。按照以往的规律,预计正式版将在12月发布。git
备注:Django 2.0 于12月2日已经正式发布。 (连接)github
2.0无疑是一个里程碑版本,移除了对 Python2.7 的支持,最少须要 3.4 以上,建议使用3.5以上的版本。web
What’s new in Django2.0 文档中一共列出了三个新的特性:正则表达式
contrib.admin
)第一个特性,主要用于动态路由定义上。在Django2.0代码实现中,主要的变化是新增了 django.urls.path
函数,它容许使用一种更加简洁、可读的路由语法。好比以前的版本的代码:express
url(r'^articles/(?P[0-9]{4})/$', views.year_archive),
在新版本中也能够写为:django
path('articles//', views.year_archive),
新语法支持类型转化,在上述的例子中, year_archive 函数接收到的year参数就变成整数而不是字符串。flask
若是你有接触过 Flask 框架,就会发现和 Variable-Rules 的语法形式和功能都是相相似的。框架
下面是 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
解决以上的两个问题。
这是一个简单的例子:
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中捕获值。/
字符。如下是根据 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”) |
文档原文是Path converters,暂且翻译为转化器。
Django默认支持如下5个转化器:
/
)以外的非空字符串,这是默认的形式对于一些复杂或者复用的须要,能够定义本身的转化器。转化器是一个类或接口,它的要求有三点:
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
使用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), ... ]
若是上述的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), ]
这段代码和以前的代码实现了基本的功能,可是仍是有一些区别:
url
是一致的。无命名分组
通常来讲,不建议使用这种方式,由于有可能引入歧义,甚至错误。
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不会当即废弃 |
将“问题引入”一节的代码使用新的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), ]
第一,目前 路由(url)到视图(View)的流程能够归纳为四个步骤:
Django2.0 和以前相比多了 变量类型转化 这一步骤。
第二,新的path语法能够解决一下如下几个场景: