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語法能夠解決一下如下幾個場景: