知識點:
1、轉換器
2、自定義轉換器
3、轉化器高階用法
一、概況
有很多請求我們URL地址後面會跟著引數,並且後端要提取到引數,比如:http://127.0.0.1:5000/center/1
這個URL地址後面有個1,可以代表我們要訪問uid為1的個人資訊。那麼我們如何提取到引數呢?這個時候就會用到Flask
的轉換器。
二、轉換器
在Flask
中支援下面這些轉換器:
轉換器 | 含義 |
---|---|
int | 接受整數 |
float | 同 int ,但是接受浮點數 |
path | 和預設的相似,但也接受斜線 |
from flask import Flask
from flask import abort, redirect, url_for
app = Flask(__name__)
@app.route('/center/<int:uid>') # 代表個人中心頁
def center(uid): # 檢視函式
return 'your uid %s' % uid # 返回內容
if __name__ == '__main__':
# 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
app.run(host='0.0.0.0', port=5000) # 執行程式
複製程式碼
在瀏覽器訪問:
如果改成:@app.route('/center/<float:uid>') # 代表個人中心頁
複製程式碼
再去訪問就會報錯,因為float
只支援浮點數。
str
型別。但是不包含/
,因為它在這裡面有特殊的意義。
@app.route('/center/<uid>') # 代表個人中心頁
複製程式碼
如果要匹配/
,請用path
轉換器:
@app.route('/center/<path:uid>') # 代表個人中心頁
複製程式碼
三、自定義轉換器
有時候系統提供的轉換器並不能滿足我們,比如我們需要的UID是至少5最多10位。如果不是這個範圍呢,我們就可以認為不滿足我們的匹配規則。而現在我們不管輸入多少位,後臺都會匹配上,然後就去執行我們的檢視。如果要排除這種現象,我們就需要自定義轉換器。
需要用到Flask
這個轉換器基類BaseConverter
from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__)
# 自定義轉換器
class MyConverter(BaseConverter):
def __init__(self, map):
super().__init__(map) # 呼叫父類
self.regex = r'\d{5,10}' # 轉換器的正則規則
app.url_map.converters['re'] = MyConverter # 註冊到converters
#會根據註冊的鍵re找到MyConverter這個類建立物件
@app.route('/center/<re:uid>') # 代表個人中心頁
def center(uid): # 檢視函式
return 'your uid %s' % uid # 返回內容
if __name__ == '__main__':
# 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
app.run(host='0.0.0.0', port=5000) # 執行程式
複製程式碼
這個在瀏覽器試下:
我們發現已經完全解決了我們剛才的問題。四、優化轉換器
我們發現這個轉化器的規則是寫死的,只能匹配UID,如果其他地方用到要匹配手機號怎麼辦,所以最好匹配規則是動態傳遞的。那麼改成如下:
from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__)
# 自定義轉換器
class MyConverter(BaseConverter):
def __init__(self, map, re):
super().__init__(map) # 呼叫父類
self.regex = re # 轉換器的正則規則
app.url_map.converters['re'] = MyConverter # 註冊到converters
#會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/center/<re(r"\d{5,10}"):uid>') # 代表個人中心頁
def center(uid): # 檢視函式
return 'your uid %s' % uid # 返回內容
@app.route('/login/<re(r"1[3456789]\d{9}"):phone>') # 代表登入頁
def login(phone): # 檢視函式
return 'your phone %s' % phone # 返回內容
if __name__ == '__main__':
# 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
app.run(host='0.0.0.0', port=5000) # 執行程式
複製程式碼
用到的時候,在把具體的正則條件傳遞進去,就好了。
五、轉換器高階用法
通過上面的一些場景我們用到了轉換器,可是既然轉換器,我們並沒有看出轉換這個兩個字在哪有體現,感覺不如叫介面卡。但是進入BaseConverter
原始碼裡面看一下,發現有兩個方法,這兩個方法是到底有什麼作用呢,不妨我們來重寫一下。
class BaseConverter(object):
"""Base class for all converters."""
regex = '[^/]+'
weight = 100
def __init__(self, map):
self.map = map
def to_python(self, value):
return value
def to_url(self, value):
return url_quote(value, charset=self.map.charset)
複製程式碼
- 重寫to_python 我們在這個方法裡面隨便返回點內容
from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__)
# 自定義轉換器
class MyConverter(BaseConverter):
def __init__(self, map, re):
super().__init__(map) # 呼叫父類
self.regex = re # 轉換器的正則規則
def to_python(self, value):
return '呵呵' # 隨便給一個返回值
app.url_map.converters['re'] = MyConverter # 註冊到converters
# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/center/<re(r"\d{5,10}"):uid>') # 代表個人中心頁
def center(uid): # 檢視函式
return 'your uid %s' % uid # 返回內容
# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/login/<re(r"1[3456789]\d{9}"):phone>') # 代表登入頁
def login(phone): # 檢視函式
return 'your phone %s' % phone # 返回內容
if __name__ == '__main__':
# 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
app.run(host='0.0.0.0', port=5000) # 執行程式
複製程式碼
當我們請求的時候發現:
如果還繼續返回value呢? def to_python(self, value):
return value # 返回value
複製程式碼
看到這我們應該明白了,父類裡面預設返回的值就是正則匹配的值,如果重寫了,傳入進來的value還是正則匹配的值,但是return的值我們可以自己改變了。比如你傳的是13888888888,那我就返回13999999999在這才有轉換的體現。到底返回什麼樣的值,還是看具體場景。
- 重寫to_url 不知道還記得我們的重定向嗎?我們可以通過重定向到任何檢視中。如果我們現在希望登入函式重定向到個人中心檢視怎麼辦?直接寫函式名字,好像不對了,因為現在路由需要一個UID引數。我們需要像下面這麼寫,並且我們在to_url方法呢隨便返回點內容:
from flask import Flask
from flask import abort, redirect, url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__)
# 自定義轉換器
class MyConverter(BaseConverter):
def __init__(self, map, re):
super().__init__(map) # 呼叫父類
self.regex = re # 轉換器的正則規則
def to_python(self, value):
return value # 返回value
def to_url(self, value):
return '呵呵' # 隨便返回點內容
app.url_map.converters['re'] = MyConverter # 註冊到converters
# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/center/<re(r"\d{5,10}"):uid>') # 代表個人中心頁
def center(uid): # 檢視函式
return 'your uid %s' % uid # 返回內容
# 會根據註冊的鍵re找到MyConverter這個類建立物件,並把規則當做初始化引數傳遞進去
@app.route('/login/<re(r"1[3456789]\d{9}"):phone>') # 代表登入頁
def login(phone): # 檢視函式
return redirect(url_for('center', uid='11111')) # 重定向到個人中心頁,uid是路由上的引數
if __name__ == '__main__':
# 0.0.0.0代表任何能代表這臺機器的地址都可以訪問
app.run(host='0.0.0.0', port=5000) # 執行程式
複製程式碼
我們在瀏覽器試一下:http://127.0.0.1:5000/login/13812345678
def to_url(self, value):
return value # 返回value
複製程式碼
我們在瀏覽器試一下:http://127.0.0.1:5000/login/13812345678
def to_python(self, value):
return '12312'
def to_url(self, value):
return value # 返回value
複製程式碼
寫到這,我們可以簡單總結一下這兩個函式什麼時候執行
- to_python 只要使了轉換器,一直會被呼叫
- to_url 只有在重定向了,並且路由上有引數的時候才會被呼叫
當我們重定向了,並傳遞引數的時候,引數會先到to_url,返回的值會去匹配路由上的正則。 如果匹配上了,就把匹配到引數傳到 to_python ,這個方法返回的值才會到檢視函式中。 如果匹配不上,就會報404錯誤。 流程如下:
歡迎關注我的公眾號: