1. 程式人生 > >Django 2.0 新款URL配置詳解

Django 2.0 新款URL配置詳解

Django2.0釋出後,很多人都擁抱變化,加入了2的行列。
但是和1.11相比,2.0在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),
]

注意:

  1. 要捕獲一段url中的值,需要使用尖括號,而不是之前的圓括號;
  2. 可以轉換捕獲到的值為指定型別,比如例子中的int。預設情況下,捕獲到的結果儲存為字串型別,不包含/這個特殊字元;
  3. 匹配模式的最開頭不需要新增/,因為預設情況下,每個url都帶一個最前面的/,既然大家都有的部分,就不用浪費時間特別寫一個了。

匹配例子:

  • /articles/2005/03/ 將匹配第三條,並呼叫views.month_archive(request, year=2005, month=3);
  • /articles/2003/匹配第一條,並呼叫views.special_case_2003(request);
  • /articles/2003將一條都匹配不上,因為它最後少了一個斜槓,而列表中的所有模式中都以斜槓結尾;
  • /articles/2003/03/building-a-django-site/ 將匹配最後一個,並呼叫views.article_detail(request, year=2003, month=3, slug="building-a-django-site"

二、path轉換器

預設情況下,Django內建下面的路徑轉換器:

  • str:匹配任何非空字串,但不含斜槓/,如果你沒有專門指定轉換器,那麼這個是預設使用的;
  • int:匹配0和正整數,返回一個int型別
  • slug:可理解為註釋、字尾、附屬等概念,是url拖在最後的一部分解釋性字元。該轉換器匹配任何ASCII字元以及連線符和下劃線,比如’ building-your-1st-django-site‘;
  • uuid:匹配一個uuid格式的物件。為了防止衝突,規定必須使用破折號,所有字母必須小寫,例如’075194d3-6885-417e-a8a8-6c931e272f00‘ 。返回一個UUID物件;
  • path:匹配任何非空字串,重點是可以包含路徑分隔符’/‘。這個轉換器可以幫助你匹配整個url而不是一段一段的url字串。

三、自定義path轉換器

其實就是寫一個類,幷包含下面的成員和屬性:

  • 類屬性regex:一個字串形式的正則表示式屬性;
  • to_python(self, value) 方法:一個用來將匹配到的字串轉換為你想要的那個資料型別,並傳遞給檢視函式。如果轉換失敗,它必須彈出ValueError異常;
  • to_url(self, value)方法:將Python資料型別轉換為一段url的方法,上面方法的反向操作。

例如,新建一個converters.py檔案,與urlconf同目錄,寫個下面的類:

class FourDigitYearConverter:
    regex = '[0-9]{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%04d' % value

寫完類後,在URLconf 中註冊,並使用它,如下所示,註冊了一個yyyy:

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的url雖然改‘配置’了,但它依然向老版本相容。而這個相容的辦法,就是用re_path()方法代替path()方法。re_path()方法在骨子裡,根本就是以前的url()方法,只不過匯入的位置變了。下面是一個例子,對比一下Django1.11時代的語法,有什麼太大的差別?

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),
]

path()方法不同的在於兩點:

  • year中匹配不到10000等非四位數字,這是正則表示式決定的
  • 傳遞給檢視的所有引數都是字串型別。而不像path()方法中可以指定轉換成某種型別。在檢視中接收引數時一定要小心。

Include

當檢視函式路徑較多時,可以使用Include()用法進行去重:

 

urlpatterns=[
	path('<page_slug>-<page_id>/history/',views.history),
	path('<page_slug>-<page_id>/edit/',views.edit),
]

等價於:

Urlpatterns = [
path('<page_slug>-<page_id>/',include([
      path(‘history/’,views.history),
      path(‘edit/’,views.edit),
]))
]

        當網站功能較多時可以在該功能資料夾裡建一個urls.py檔案,將該功能模組下的url全部寫在該檔案裡。但是要在全域性的urls.py中使用include方法實現url對映分發。

例如:網站有論壇模組,則在論壇模組下建個urls.py檔案,將與論壇相關的頁面的url全部寫在這個檔案裡,然後在全域性的urls.py檔案裡這樣寫:

from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('ant_test/',include('ant_test.urls'))
]