Flask URL默認轉換器、自定義轉換器、to_python、to_url
- 2019 年 11 月 13 日
- 筆記
Flask框架自帶的轉換器類型
- int轉換器
<int:param>
:接收整數 - float轉換器
<float:param>
: 接收浮點數 - string轉換器
<string:param>
: 接收string類型(默認則是string轉換器) - path轉換器
<path:param>
:和默認的相似,但也接收斜線
設置int類型的路徑參數
# 轉換器 <int:goods_id> @app.route('/goods_info/<int:goods_id>') def goods_info(goods_id): return "goods_id is %d" % goods_id
測試訪問 http://127.0.0.1:5000/goods_info/123

設置float轉換器的路徑參數
# 設置float轉換器 @app.route('/goods_info/<float:goods_id>') def goods_info(goods_id): return "goods_id is %s" % goods_id

可以發現參數為float參數是能夠正常訪問處理的。

當傳遞參數為 123 整數的時候,則報錯Not Found。

當傳遞參數為 hello 字符串的時候,則報錯Not Found。
設置string類型的路徑參數
# 設置轉換器 <string:goods_id> @app.route('/goods_info/<string:goods_id>') def goods_info(goods_id): return "goods_id is %s" % goods_id
測試訪問 http://127.0.0.1:5000/goods_info/你好

可以看到中文的字符串參數也是可以直接獲取的。
- 其中如果轉換器不寫類型,默認就是string類型的,示例如下:
# 設置轉換器 默認是string @app.route('/goods_info/<goods_id>') def goods_info(goods_id): return "goods_id is %s" % goods_id
設置path轉換器的路徑參數
# 設置path轉換器 @app.route('/goods_info/<path:goods_id>') def goods_info(goods_id): return "goods_id is %s" % goods_id
測試訪問:http://127.0.0.1:5000/goods_info/hello//world/123

可以看到 path轉換器 可以接收斜杠 /
將後面所有的字符串都作為參數傳遞。
上面的這幾種Flask自帶的轉換器雖然可以設置很多參數了,但是還是無法匹配一些特殊需求的路徑參數。
例如:在發送短訊的URL中,路徑參數設置為手機號碼,上面的自帶類型就無法精確匹配手機號碼了。
這時候就需要自定義路由轉換器出場了。
自定義路由轉換器
1.自定義路由轉換器的基礎類:
from werkzeug.routing import BaseConverter
2.創建自定義轉換器,以及將轉換器加入Flask應用中:
# 創建自定義轉換器 # 1. 定義自己的轉換器 class RegexConverter(BaseConverter): """""" def __init__(self, url_map, regex): """ :param url_map: 固定傳遞的參數,用於調用父類的初始化方法 :param regex: 從url使用()傳遞過來的正則參數 """ # 調用父類的初始化方法 super(RegexConverter, self).__init__(url_map) # 將正則表達式的參數保存到對象的屬性中,flask會去使用這個屬性來進行路由的正則匹配 self.regex = regex # 2. 將自定義的轉換器添加到flask的應用中 app.url_map.converters["re"] = RegexConverter
3.在視圖函數中設置自定義路由轉換器re
:
# 127.0.0.1:5000/send/18912345678 # <re(r''): param> 使用re自定義轉換器,其中()則是需要傳遞的參數 @app.route("/send/<re(r'1[34578]d{9}'):mobile_num>") def send_sms(mobile_num): return "send sms to %s" % mobile_num
4.測試訪問符合正則匹配的電話號碼的url
訪問 http://127.0.0.1:5000/send/18912345678

5.測試訪問不符合正則匹配的url
訪問 http://127.0.0.1:5000/send/189123

根據不符合正則匹配的URL參數,則報錯Not Found。從效果來看,就可以知道通過這個自定義的轉換器,我們可以實現這種特殊的參數獲取。
創建專屬手機號碼的轉換器
上面的轉換器可以傳遞正則匹配的規則,屬於一種萬能轉換器,下面將其創建一個專屬手機號碼的轉換器。
# 創建Moblie的專屬轉換器 class MobileConverter(BaseConverter): def __init__(self,url_map): # super(MobileConverter,self).__init__(url_map) # 調用父類方法一 super().__init__(url_map) # 調用父類方法二 self.regex = r'1[34578]d{9}' # 註冊MobileConverter轉換器 app.url_map.converters["mobile"] = MobileConverter # 設置視圖函數 @app.route("/send/<mobile:mobile_num>") def send_sms(mobile_num): return "send sms to %s" % mobile_num
其實這個例子主要是想說明Flask可以創建多個自定義轉換器。
另外,在Django中有中間類這個類方法來處理url請求至視圖函數之間的業務處理,例如:權限驗證,session數據記錄等等。
在Flask中可以使用專屬轉換器的to_python
和to_url
兩個函數來實現類似中間類這樣的功能。
下面來看看。
查看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): if isinstance(value, (bytes, bytearray)): return _fast_url_quote(value) return _fast_url_quote(text_type(value).encode(self.map.charset))
首先從源碼來分析一下這個繼承類中to_python
和to_url
函數。
- to_python 將url傳遞的參數,直接將其傳遞至視圖函數之中
- to_url 則是當另一個視圖函數使用
url_for()
這個方法跳至該轉換器的時候,會將url的參數傳遞到url路徑的參數中。
單單這麼解釋有些抽象,下面來看看示例。
to_python 函數
# 創建Moblie的專屬轉換器 class MobileConverter(BaseConverter): def __init__(self,url_map): # super(MobileConverter,self).__init__(url_map) super().__init__(url_map) self.regex = r'1[34578]d{9}' def to_python(self, value): """""" print("to_python方法被調用") # value是在路徑進行正則表達式匹配的時候提取的參數 return "abc" # 該value會傳遞到視圖函數中 app.url_map.converters["mobile"] = MobileConverter @app.route("/send/<mobile:mobile_num>") def send_sms(mobile_num): return "send sms to %s" % mobile_num
此時測試訪問 http://127.0.0.1:5000/send/18912345678
按照原來訪問後在瀏覽器會打印 send sms to 18912345678 的信息,但是由於to_python
設置返回是 "abc",所以瀏覽器將會打印 send sms to abc,下面來瀏覽器執行驗證看看,如下:

從瀏覽器就可以判斷出to_python
方法就是url傳遞到視圖函數中間的業務處理方法,其實就相當於Django的中間類。
如果有權限驗證類的需求,可以在to_python
中實現。
to_url 函數
# 創建Moblie的專屬轉換器 class MobileConverter(BaseConverter): def __init__(self,url_map): # super(MobileConverter,self).__init__(url_map) super().__init__(url_map) self.regex = r'1[34578]d{9}' def to_python(self, value): """""" print("to_python方法被調用") # value是在路徑進行正則表達式匹配的時候提取的參數 return value # 該value會傳遞到視圖函數中 def to_url(self, value): """使用url_for的方法的時候被調用""" print("to_url方法被調用") return "15811111111" # 該value會修改url路徑中的參數為 15811111111 app.url_map.converters["mobile"] = MobileConverter @app.route("/send/<mobile:mobile_num>") def send_sms(mobile_num): return "send sms to %s" % mobile_num @app.route("/hello_send") def hello_send(): return redirect(url_for('send_sms', mobile_num=18612345678))
這個示例是首先訪問 hello_send 視圖函數,然後使用 url_for函數跳轉至 send_sms 視圖函數。
在這種過程中,hello_send 視圖函數跳轉的時候設置的路徑參數為 mobile_num=18612345678。
那麼正常在瀏覽器轉發後的url訪問應該是:http://127.0.0.1:5000/send/18612345678
但是由於to_url返回的是15811111111,所以最終跳轉的url顯示會是 http://127.0.0.1:5000/send/15811111111
下面來確認看看,訪問http://127.0.0.1:5000/hello_send

可以從圖中的傳遞說明,應該基本上都可以看出參數的傳遞過程。