iT邦幫忙

0

Django學習紀錄 5.視圖與URL[附正規表達式的整理]

之前有在用Django寫一些小網站,現在暑假想說再來複習一下之前買的這本書
https://ithelp.ithome.com.tw/upload/images/20190724/20118889bj9fH1vhuR.jpg
於是我就把它寫成一系列的文章,也方便查語法
而且因為這本書大概是2014年出的,如今Django也已經出到2.多版
有些內容也變得不再支援或適用,而且語法或許也改變了
所以我會以最新版的Python和Django來修正這本書的內容跟程式碼

目錄:django系列文章-Django學習紀錄

5. 視圖與URL

5.1 第一個視圖:媽,我在這裡

這次我們的目標是要讓 127.0.0.1:8000/here 這個網址可以對應到我們自己寫的頁面
https://ithelp.ithome.com.tw/upload/images/20190713/20118889ubYskSZCvl.png
不過因為書上的url配置是舊版的django語法,在新版的django中新增了path以及re_path的用法
在下層的mysite中新增檔案views.py
在下層的mysite中找到url.py這個檔案
設置

from django.contrib import admin
from django.urls import path
from mysite.views import here # <-加入這行

urlpatterns = [
    path('admin/', admin.site.urls),
    path('here/', here), # <-加入這行
]

記得之前我們說過BASE_DIR是專案目錄
所以from mysite.views import here這行會從專案目錄(即上層mysite)去找
也就是從下層的mysite的views.py這個檔案引入here這個函式
接著設置views.py檔案

from django.http import HttpResponse

def here(request):
    return HttpResponse('Mom, I am here!')

這類的視圖函式都要以request作為第一個參數,因為任何的回應一定都要伴隨著一個要求
這樣django才能獲取你所要求的資訊
HttpResponse是一個基礎的回應物件,可以回傳一個完整的html或字串
設置完畢後,重新啟動伺服器

python manage.py runserver

當使用者進到 127.0.0.1:8000/here 這個網址時
就會成功看到我們設置的字串
注意一下

path('here/', here)

這樣子設置
不管輸入 127.0.0.1:8000/here
或是 127.0.0.1:8000/here/
都會成功對應
但是如果設置成

path('here', here)

這兩種網址都不會被成功對應到
因為django預設如果進入的網址最後面沒有/,它會自動幫你補/
所以切記path的每個url pattern最後都要加上/
在舊版的python中
如果想要非英文字串,例如

from django.http import HttpResponse

def here(request):
    return HttpResponse('媽,我在這!')

可能會出現編碼的錯誤訊息
這時可能要在views.py開頭加上

# -*- coding: utf-8 -*-

不過我們用的都是最新版的所以應該不會產生編碼問題

5.2 第二個視圖:網址計算機

我們想要做一個譬如進入 127.0.0.1:8000/23/plus/2 這個網址
就會自動幫你計算23+2=25
像這樣
https://ithelp.ithome.com.tw/upload/images/20190713/20118889rlT1HQxGKL.png
這樣的話就會用到"正規表達式"了
這時就必須使用re_path
設置urls.py

from django.contrib import admin
from django.urls import path, re_path # <-引進re_path
from mysite.views import here, add # <-引進add

urlpatterns = [
    path('admin/', admin.site.urls),
    path('here/', here),
    re_path(r'(\d{1,2})/plus/(\d{1,2})', add) # <- 加入這行
]

在正規表達式中,\d{1,2}代表匹配1位數或2位數整數(即0~99)
前面的r代表了這個字串是正規表達式(regular expression)
不過這個r你可以不要加,只是pylint會建議你加
而且如果有加r的話在VS code編輯器裡的樣子會變很好看
並且方便除錯
對了順便一提如果用re_path的話就不需要在最後面加上/
接著設置views.py

from django.http import HttpResponse

def here(request):
    return HttpResponse('媽,我在這!')

def add(request, a, b): # <- 加入這個函式
    s = int(a) + int(b)
    return HttpResponse(s)

這裡有個重點,url pattern是可以被當作參數的!
只要把\d{1,2}用括號括起來變成(\d{1,2})
括號裡的東西就可以照順序被當成參數分別傳到a與b裡
被傳入的參數預設都是字串
所以要用int()函式轉換成整數
接下來我們想要讓它不只可以做加法
而是能夠做所有的四則運算,例如
https://ithelp.ithome.com.tw/upload/images/20190713/20118889XS9LobCN5P.png
設置urls.py

from django.contrib import admin
from django.urls import path, re_path
from mysite.views import here, add, math # <-加入math

urlpatterns = [
    path('admin/', admin.site.urls),
    path('here/', here),
    re_path(r'(\d{1,2})/plus/(\d{1,2})/', add),
    re_path(r'(\d{1,2})/math/(\d{1,2})/', math), # <-加入這行
]

views.py

from django.http import HttpResponse

def here(request):
    return HttpResponse('媽,我在這!')

def add(request, a, b):
    s = int(a) + int(b)
    return HttpResponse(s)

def math(request, a, b): # 加入
    a = int(a)
    b = int(b)
    s = a + b
    d = a - b
    p = a * b
    q = a / b
    html = '<html>sum={s}<br>dif={d}<br>pro={p}<br>quo={q}</html>'.format(s=s, d=d, p=p, q=q)
    return HttpResponse(html)

小提醒一下python3
/是正常除法 //才是取商
html中 <br>是換行
介紹另一種在Django2.0以上的寫法,譬如剛剛的這行

re_path(r'(\d{1,2})/math/(\d{1,2})/', math)

也可以寫成這樣

path('<str:a>/math/<str:b>', math)

str也可以換成int之類的,這樣視圖函式中就不用把參數用int()轉換型別了
是不是很方便呢~

有關正規表達式

regular expression(簡稱regex)
推薦一個網站
在寫正規表達式的時候可以測
https://regex101.com/
這邊整理一些常用的正規表達式(來自文淵閣的python初學特訓班書籍p.5-6)

正規表達式 代表
. 一個除了換行字元\n以外的所有字元
^ 輸入列的開始
& 輸入列的結束
? 前一個項目可以出現0次或1次
[abc] 代表一個符合a或b或c的任何字元
[a-z] 代表一個符合字母a~z的任何字元
\ 代表後面的字元以一般字元處理
{m} 代表前一個項目必須正好出現m次
{m,} 代表前一個項目出現次數最少m次,最多無限次
{m,n} 代表前一個項目出現次數最少m次,最多n次
\d 一個數字字元,相當於[0123456789][0-9]
^ 對後面的項目做反運算,例如:[^a-d]代表除了a、b、c、d外的所有字元
\D 一個非數字字元,相當於[^0-9]
\n 換列字元
\r 回列首字元(carriage return)
\t tab定位字元
\s 空白字元,相當於[\r\t\n\f]
\S 非空白字元,相當於[^\r\t\n\f]
\w 一個數字、字母或底線字元,相當於[0-9a-zA-Z_]
\W 一個非數字、字母或底線字元,相當於[^\w],即[^0-9a-zA-Z_]
* 前一個項目可以出現0次或無限多次
+ 前一個項目可以出現1次或無限多次

正規表達式的範例

語法 正規表達式 範例
整數 [0-9]+ 33025
浮點數 [0-9]+\.[0-9]+ 75.93
英文單字 [A-Za-z]+ Python
變數名稱 [A-Za-z_][A-Za-z0-9_]* _pointer
Email [a-zA-Z0-9_]+@[a-zA-Z0-9\._]+ guest@kimo.com.tw
URL https:\/\/[a-zA-Z0-9\.\/_]+ https://www.google.com.tw/

剛才的網址計算機只能算1位數整數或2位數整數
如果要擴大為所有整數與浮點數
那就改成

re_path(r'([0-9]+\.*[0-9]*)/math/([0-9]+\.*[0-9]*)', math)
def math(request, a, b):
    a = float(a)
    b = float(b)
    s = a + b
    d = a - b
    p = a * b
    q = a / b
    html = '<html>sum={s}<br>dif={d}<br>pro={p}<br>quo={q}</html>'.format(s=s, d=d, p=p, q=q)
    return HttpResponse(html)

這樣就行囉

上一篇:Django學習紀錄 3.Django介紹與安裝 4.建置與環境設定[使用VS code作為開發環境]

下一篇:Django學習紀錄 6.模板初探


尚未有邦友留言

立即登入留言