iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 24
0
Modern Web

From Django 1.11 to Django 2.1 系列 第 24

Day24 : 深入探討 命名空間

Day23 的一些命名空間的介紹,才讓我有機會進入命名空間這一個坑,官網上所介紹的命名空間其實要來的複雜許多

原本想要在 Day23 再額外介紹 更深入的命名空間,但是我發現內容多到可以直接上一篇新的xD

Day23 介紹的只是一個最直觀且易懂的方法

今天的主題原本不在計畫中,我原本不打算用這一招的

https://ithelp.ithome.com.tw/upload/images/20181024/20111829xTDRKcGc0a.jpg

但是頭都栽下去了,在找資料的過程中發現這一個議題,並沒有看到中文網站在介紹這個 (或許是我關鍵字下的太差...

還是有拉,但是我還是不懂,感覺像是在看照文本翻譯的教學

所以今天的主題著重在 深入探討 命名空間 !

再次強調,官網講得很清楚,不過範例給得太少且用字晦澀,如果你是第一看的人,很難能夠領悟


轉換 命名空間
這邊我會附上官網的教學,你可以做對照,相信你能更容易領悟!

在開始之前,先帶大家了解命名空間 其實分成兩種,我們可以分別把它們想成 本名綽號

  1. 應用命名空間 (Application Namespace) : 本名
  2. 實例命名空間 (Instance Namespace) : 綽號

這裡要先強調一個觀念,實例命名空間必須唯一,想想看,一個人會有很多個綽號,但是你不可能幫別人取兩次相同的綽號,對吧 ^^

接著我會透過 Day23的範例替大家說明 命名空間搜尋的規則

# top-level urls.py
from django.contrib import admin
from django.urls import path, include
from .views import test
urlpatterns = [
    path('admin/', admin.site.urls),
    # vendors app 有兩個綽號 f-vendors 及 s-vendors
    path('welcome/', include('vendor.urls', namespace='f-vendors')),
    path('vendor/', include('vendor.urls', namespace='s-vendors')),
    path('test/', test, name='index'),
]

# vendor/urls.py
from django.contrib import admin
from django.urls import path

from . import views
app_name = 'vendors'
urlpatterns = [
    path('', views.showtemplate, name='index'),
    path('<int:id>/', views.singleVendor, name='vendor_id'),
    path('create', views.vendor_create_view, name='create'),
    path('fcreate', views.food_create_view, ),
]

因為版面關係,這裡用 App Namespcae 代表 Application Namespace

假如我們要搜尋的是 vendors:index,這它的搜尋規則是

  1. 先找 應用命名空間(App Namespace) - 也就是我們的 app_name,如果存在,則接下來找底下的特徵(就是path() 每一個定義的 name),而此時 app_name的特徵有 index、vendor_id、create
  2. 如果 應用命名空間底下的特徵有符合我們要搜尋的 index,它所 反轉 (reverse) 的網址便是對應到前方的'',因此網址便是 vendor/
  3. 如果找不到符合的命名空間,則接下來會試著去找 預設應用命名空間(Default App Namespace),它的概念便是去找與自己名稱相符的綽號,也就是說 實例命名空間 可以和 應用命名空間 取相同的名稱,這種情況下,這個實例命名空間就是應用命名空間的 預設應用命名空間
  4. 但如果剛好我們的綽號都沒有相符,那便是代表我們沒有預設應用命名空間,下一個步驟便是去找,所有綽號中最後一個取的綽號,也就是 s-vendors
  5. 最後一步,就是如果在第一步已經沒有找到相符應用命名空間,則會直接去找綽號 - 實例命名空間

接下來直接帶大家看範例!

因為第1步及第2步已經帶大家了解過了,所以我們直接說明 3~5

我創建一個 test.html 來帶大家了解,可以搭配著 urls.py 來看

# top-level urls.py
from django.contrib import admin
from django.urls import path, include
from .views import test
urlpatterns = [
    ...略
    # vendors app 有兩個綽號 f-vendors 及 s-vendors
    path('welcome/', include('vendor.urls', namespace='f-vendors')),
    path('vendor/', include('vendor.urls', namespace='s-vendors')),
    path('test/', test, name='index'),
]
<p> vendors:index :</p> {% url 'vendors:index' %}<br/>

因為此時我的 {% url 'vendors:index' %} 不是建立在 app_name - vendors底下,所以找不到符合的應用命名空間(3),所以會用最後一個被綁定的實例空間 - s-vendor

此時我們的網頁上就會秀出 /vendor/
https://ithelp.ithome.com.tw/upload/images/20181024/20111829yCNrG67c0j.jpg

而當你調皮搗蛋 交換了綽號的位置

urlpatterns = [
    ...略
    # 互換位置
    path('vendor/', include('vendor.urls', namespace='s-vendors')),
    path('welcome/', include('vendor.urls', namespace='f-vendors')),
    path('test/', test, name='index'),
]

此時我們的網頁上就會秀出 /welcome/
https://ithelp.ithome.com.tw/upload/images/20181024/201118293Z9dO3fliv.jpg

也就是說! 因為找不到 預設的應用命名空間,所以它就用最後一個被綁定的!
但此時如果你又將 test.html 改成這樣

urlpatterns = [
    ...略
    # 出現了 預設應用命名空間
    path('vendor/', include('vendor.urls', namespace='vendors')),
    path('welcome/', include('vendor.urls', namespace='f-vendors')),
    path('test/', test, name='index'),
]

我們網頁就會重新秀出 /vendor/,因為 預設應用命名空間 出現了,所以它就先採納 預設應用命名空間,而不是 最後一個被綁定的!
https://ithelp.ithome.com.tw/upload/images/20181024/20111829QdFf2mqJcT.jpg

最後,我們將 test.html 修改成這樣

<p>s-vendors:index :</p> {% url 's-vendors:index' %}<br/>
<p>f-vendors:index :</p> {% url 'f-vendors:index' %}<br/>

此時我們的網頁上就會秀出
https://ithelp.ithome.com.tw/upload/images/20181024/201118291JzP8Vo5TI.jpg

因為 應用命名空間 找不到,所以就改用 實例命名空間 去找囉!

那又如果說... 你不替 實例命名空間 取綽號

urlpatterns = [
    ...略
    #不定義 綽號 - 實例命名空間,則主動被授予 應用命名空間
    path('vendor/', include('vendor.urls')),
    path('welcome/', include('vendor.urls')),
    path('test/', test, name='index'),
]

那麼 Django 會自動將自己的 應用命名空間 給它們當 實例命名空間,但是 Django 會警告你不要這麼做! 因為此時這兩個傢伙 使用相同的綽號 - vendors

WARNINGS:
?: (urls.W005) URL namespace 'vendors' isn't unique. You may not be able to reverse all >URLs in this namespace

所以此時大家都擁有 預設應用命名空間,而我們的規則是,誰有 預設命名空間,誰就會被使用

<p> vendors:index :</p> {% url 'vendors:index' %}<br/>

https://ithelp.ithome.com.tw/upload/images/20181024/20111829ST6sRBMf3y.jpg

呼,此時的你問了 : 這樣的命名有什麼幫助? 就拿官網的投票網站來做說明吧!
它可以應用在區別 使用者 及 管理者,也就是說 投票系統都做在一起,但是透過不同的身分(也就是不同的權限!)去瀏覽相同的網頁,而不用說要為不同身分去作兩個投票系統 ^^"


今日小節

今天我們深入探討了命名空間,主要覺得這議題也蠻重要的,雖然遠遠不及單純的使用 app_name:xxxxx 來的直觀,不過多學點總不是壞事 ^^,希望這對你有幫助!

如果這篇 命名空間 的介紹有誤的,歡迎各方好手指點,感恩~

From BY


上一篇
Day23 : Django 命名空間
下一篇
Day25 : Django Class-Based Views (CBV)
系列文
From Django 1.11 to Django 2.1 30

尚未有邦友留言

立即登入留言