之前有在用Django寫一些小網站,現在暑假想說再來複習一下之前買的這本書
於是我就把它寫成一系列的文章,也方便查語法
而且因為這本書大概是2014年出的,如今Django也已經出到2.多版
有些內容也變得不再支援或適用,而且語法或許也改變了
所以我會以最新版的Python和Django來修正這本書的內容跟程式碼
這次我們的目標是要讓 127.0.0.1:8000/here 這個網址可以對應到我們自己寫的頁面
不過因為書上的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 -*-
不過我們用的都是最新版的所以應該不會產生編碼問題
我們想要做一個譬如進入 127.0.0.1:8000/23/plus/2 這個網址
就會自動幫你計算23+2=25
像這樣
這樣的話就會用到"正規表達式"了
這時就必須使用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()函式轉換成整數
接下來我們想要讓它不只可以做加法
而是能夠做所有的四則運算,例如
設置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)
這樣就行囉