iT邦幫忙

2023 iThome 鐵人賽

DAY 30
0
自我挑戰組

Django 初學入門 - 從 ROR 的角度來學習 Django系列 第 30

DAY30 - 介紹 Django 進階的 url 設定 + 結語

  • 分享至 

  • xImage
  •  

今天是最後一天!我們來學一下如何使用進階的路徑設定,也就是怎麼在路徑上面使用正規表達式。

進階路徑設定 - re_path

我們前面設定路徑的時候,都是用 path,來達成我們想要設定的路徑,但是有時候在設定路徑時,我們設定的規則不會這麼簡單,有時候會加上一些限定的條件,讓該路徑被使用時,是有 規則/限制 的,那要怎麼達成這個目的呢?這邊就可以利用 正規表達式 regular expression,來達成我們的目標。

PS. 如果聽不懂沒關係,我們來看下面的實際案例

第一個範例

我們用這次使用到的 產品 Product 當作範例,首先我們看下面這兩行程式,這兩行程式的意思是一樣的:

# 原先的路徑設定
path("product/<int:pk>", views.ProductDetailView.as_view(), name="product-detail"),

# 使用正規表達式的路徑設定
re_path(r'^product/(?P<pk>\d+)$', views.ProductDetailView.as_view(), name="product-detail"),

原先我們在設定 product-detail 路徑的時候,是用 path 來設定,那一段最後對應的 url 是這樣, http://127.0.0.1:8000/online/product/2 撇除前段路徑 http://127.0.0.1:8000/online/ 不看,真正用到的是這一段 product/2,這邊也很容易了解,這一段是對應上 product/<int:pk> 的,這邊的 <int:pk> 就是對應上物件的 primary key

今天當我們換使用 re_path 呢?為什麼會跟 path 的意義一樣呢?我們實際換一次就知道了,下面是產品原本的路徑設定:

# store/online/urls.py
urlpatterns += [
    path("products/", views.ProductListView.as_view(), name='product-list'),
    path("product/create/", views.ProductCreate.as_view(), name='product-create'),    
    path("product/<int:pk>", views.ProductDetailView.as_view(), name="product-detail"),
    path("product/<int:pk>/update/", views.ProductUpdate.as_view(), name="product-update"),   
    path("product/<int:pk>/delete/", views.ProductDelete.as_view(), name="product-delete"),  
]

改成下面這樣:

# store/online/urls.py

from django.urls import path, re_path

urlpatterns += [
    path("products/", views.ProductListView.as_view(), name='product-list'),
    path("product/create/", views.ProductCreate.as_view(), name='product-create'),    
    # 修改這一段 
    re_path(r'^product/(?P<pk>\d+)$', views.ProductDetailView.as_view(), name="product-detail"),
    # 修改這一段 
    path("product/<int:pk>/update/", views.ProductUpdate.as_view(), name="product-update"),   
    path("product/<int:pk>/delete/", views.ProductDelete.as_view(), name="product-delete"),  
]

這樣修改好後,我們到瀏覽器輸入以下網址 http://127.0.0.1:8000/online/product/1 (要確保你有商品喔),應該可看到以下畫面:

https://ithelp.ithome.com.tw/upload/images/20231011/20162365pMAvckKoRd.png

發現這樣改後,我們的 product-detail 頁面也可以正常運行,代表這兩段式相同的意思,那接下來我們就來解釋 re_path 這一段是什麼意思拉~

re_path 解釋

要釐清這一段的意思前,我們要先了解關於 正規表達式 regular expression 的各種符號意義,因此來看以下的圖表,以下圖表是從 https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views MDN Django 教學找到的,原本是英文,因此我這邊只是單純把它翻成中文~

符號 意義
^ 匹配文字的開頭
$ 匹配文字的結尾
\d 匹配數字(0, 1, 2....9)
\w 匹配單字字符,例如 字母表中的任何大寫或小寫字元、數字或底線字元 (_)
+ 匹配一個或多個前面的字元。 例如,要符合一位或多位數字,您可以使用 \d+。 要匹配一個或多個“a”字符,您可以使用 a+
* 匹配零個前面的字元。 例如,如果不匹配任何內容或一個單詞,您可以使用 \w
() 捕捉括號內的模式(pattern)部分。 任何捕獲的值都將作為未命名參數傳遞到視圖(如果捕獲了多個模式(pattern),則將按照捕獲的順序提供關聯參數)
(?P<name>...) 將模式(pattern)捕獲為命名變數(在本例中為'name')。 捕獲的值將傳遞到具有指定名稱的views。 因此,您的 views 必須宣告一個同名的參數!
[] 與中括號中的任一個字元相符。 例如,[abc] 將符合'a'、'b'或'c'。 [-\w]將匹配“-”字元或任何單字字元。

解析

看完符號定義表後,我們來拆解剛剛那一段的 re_path - (r'^product/(?P<pk>\d+)$'):

re_path(r'^product/(?P<pk>\d+)$', views.ProductDetailView.as_view(), name="product-detail"),
  1. 首先 r 開頭,並且用 '' 把接下來的連結規則包在裡面
  2. ^product/: 代表整段連結 開頭product/
  3. (?P<pk>\d+): 代表會捕捉所有的數字,並且把這些數字當作 pk 變數,傳到 views 那邊使用
  4. $: 最後結尾

例如: 如果今天我的連結是這樣: http://127.0.0.1:8000/online/product/1222,他會傳對應到 /product/1222,並且傳遞變數 pk='1222' 到指定的 view (這邊的 view 就是ProductDetailView)

其他範例

範例一

re_path(r'^product/(\d+)$')

上面的範例跟 (r'^product/(?P<pk>\d+)$') 有點像,不過差異就在一個有指定變數名稱(pk),一個沒有,所以今天假設 re_path 是這樣寫 (r'^product/(\d+)$'),當我們連結輸入 http://127.0.0.1:8000/online/product/1222時,會朝 views 送一個沒有命名的變數,且該值為 1222

範例二

re_path(r'^product/(?P<stub>[-\w]+)$')

這個跟剛剛比起來稍稍不太一樣,讓我們來解釋一下吧~

  1. 首先 r 開頭,並且用 '' 把接下來的連結規則包在裡面
  2. ^product/: 代表整段連結 開頭product/
  3. (?P<stub>[-\w]+): 這一段為捕捉 數個 '-' 和 \w(文字),抓到後一起把他們當作變數(stub),傳到 views 那邊使用
  4. $: 最後結尾

此案例是一種設定 url 路徑很典型的模式,因為 stub 是一種基於 文字版的primary key,聽不懂這一句話沒關係,我們直接看下面的例子。

以往我們看個別產品的詳細資訊,路徑都是這樣 http://127.0.0.1:8000/online/product/1222,但是假設今天我不想用數字代表這個產品,我想要用英文字,像這樣: http://127.0.0.1:8000/online/product/lufy-comic-books,像這樣用英文字,就可以知道這個產品代表的意義,如果今天只是單純用數字就看不出來這個產品是什麼。

因此如果想要用英文取代數字的話,就可以把路徑換成這樣:re_path(r'^product/(?P<stub>[-\w]+)$')

結語

終於完賽拉~~~~今天就是第 30 天,也是我第一次參加鐵人賽的最後一天,也因為這一次的經歷,希望讓跟我一樣的人,從原本寫 ROR 的人,跳到 Django 的學習成本可以不要這麼高!

以下附上我在寫這30天文章時參考網站:

Django MDN: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Introduction
Django 官網: https://www.djangoproject.com/
pyenv 安裝、指令: https://ephrain.net/python-%E4%BD%BF%E7%94%A8-pyenv-%E5%9C%A8-mac-%E4%B8%8A%E5%AE%89%E8%A3%9D%E5%B7%B2%E7%B6%93%E6%B6%88%E5%A4%B1%E7%9A%84-python-2-%E7%89%88%E6%9C%AC/


上一篇
DAY29 - Django 登入權限驗證
系列文
Django 初學入門 - 從 ROR 的角度來學習 Django30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言