在開始轉換器的內容之前,我們先來看下頁面的鏈接跳轉,這在我們的網站中會經常看到:
from flask import Flask
from flask import redirect # 頁面跳轉的方法
from flask import url_for # 通過視圖函數名反向推出路由路徑
app = Flask(__name__)
app.config.from_pyfile('./config.cfg')
@app.route('/index',methods = ['GET','POST'])
def index():
return 'This is index page'
@app.route('/login')
def login():
url = url_for('index') # 通過視圖函數index推出index對應的路由
return redirect(url) # 跳轉到指定地址
print(app.url_map)
if __name__ == '__main__':
app.run()
我們可以看到,當我們訪問/login的時候,馬上重定向到了/index,即跳轉到了/index下;
好了,接下來我們來講轉換器:
設想一種情況,一個購物網站,它有很多類別和商品信息,那麼這樣就會造成很多的訪問鏈接地址,如果我們一個一個創建肯定不合適,我們可以通過轉換器將每種商品的ID提取出來,作爲視圖函數的參數進行調用,後期再通過數據庫將數據進行填充就好了;
from flask import Flask
app = Flask(__name__)
app.config.from_pyfile('./config.cfg')
@app.route('/goods/<int:goods_id>')
# 這裏需要說明的是:引號包含的還是路由地址,只是<int:goods_id>就像變量一樣,這裏int指的就是數據類型,
# 可以爲int、float和path三種,默認情況下當做string處理;goods_id就像是變量名一樣
# 注意:不可包含/,不然會被誤判爲地址
def goods_detail(goods_id): # 這裏的參數就是上面通過轉換器提取出來的數據
return 'goods detail page %s' % goods_id
print(app.url_map)
if __name__ == '__main__':
app.run()
通過上面的栗子相信已經基本瞭解了轉換器的作用,那麼上面例子的轉換規則還是太簡單了,還記得正則表達式是怎麼使用的嘛,我們可以用正則表達式來定義轉換規則:
from werkzeug.routing import BaseConverter
'''
flask中路由部分就是通過werkzeug這個庫來實現的,那麼我們對路由路徑的處理就需要用到這個庫
'''
from flask import Flask
app = Flask(__name__)
# 下面我們就需要做一個根據我們自定義正則規則來提取信息的萬能轉換器
class RegConverter(BaseConverter): # 定義轉換器類,繼承父類的屬性和方法
def __init__(self,url_map,regex): # 初始化操作
# 我們可以看見有兩個參數:regex - 自定義的規則
# url_map是默認自己添加上去的,在構建默認轉換器對象的時候,會把當前整個app應用裏的路由列表傳到第一個參數裏面
super(RegConverter,self).__init__(url_map) # 初始化父類
# 在使用我們自定義的轉換器之前,先以父類最原始的方式將對象構建出來,構建出來之後,再把我們定義的參數保存
self.regex = regex
# 將正則表達式的規則保存到regex這個屬性中,flask會使用這個屬性來進行路由的正則匹配
app.url_map.converters['re'] = RegConverter
# 將自定義的轉換器添加到flask的應用中
@app.route("/goods/<re('1[234]\d{5}'):goods_id>")
# 上面就是自定義正則規則,[]裏面就是限制字符,{n}就是限制字符格式
def goods_detail(goods_id):
return 'goods_id : %s' % goods_id
if __name__ == '__main__':
app.run(debug=True)
接下來我們來看下轉換器的高級應用,從上面我們知道自定義轉換器是基於BaseConverter來實現的,那麼我們看下這個父類都做了些什麼吧:
class BaseConverter(object):
"""Base class for all converters."""
regex = "[^/]+" # 我們可以看見默認規則是:在/之前的所有字符
weight = 100 # 最長爲100
def __init__(self, map):
self.map = map # 這就是我們爲什麼要上傳url_map的原因
def to_python(self, value):
# 這個方法就是當拿到正則表達式提取後的值,再要如何進行處理,默認是將值直接返回了,我們可以再這個做進一步的出來再返回
return value
def to_url(self, value):
# 這個方法我們從功能代碼可以看出來,它對url進行了處理,並且放回了一個合法的url,它在我們進行頁面跳轉,但是路由路徑存在轉換器轉換的時候存在
if isinstance(value, (bytes, bytearray)):
return _fast_url_quote(value)
return _fast_url_quote(text_type(value).encode(self.map.charset))
我們通過兩個例子來分別說明:
- to_python()方法的使用:
from werkzeug.routing import BaseConverter from flask import Flask app = Flask(__name__) class RegConverter(BaseConverter): def __init__(self,url_map,regex): super(RegConverter,self).__init__(url_map) self.regex = regex def to_python(self, value): return 'py'+value # 對返回結果進行處理 app.url_map.converters['re'] = RegConverter @app.route("/goods/<re('1[234]\d{5}'):goods_id>") def goods_detail(goods_id): return 'goods_id : %s' % goods_id if __name__ == '__main__': app.run(debug=True)
我們發現,跟之前的代碼,所有的定義規則什麼都是一樣的,但是在輸出的時候卻多了‘py’,這是因爲在獲得轉換結果之後,在對結果返回之前,我們在代碼中進行了處理,所以返回的值不是轉換之後得到的值了;我們可以在這一步對數據進行加密,或者其他操作; - to_url()的意義是什麼呢?
我們在文章最開始的時候說了,網頁和網頁之間會存在跳轉關係,並且可以通過url_for(視圖函數)推出路由的地址,那麼現在問題來了,當我的路由是有轉換器轉換的,地址就是不確定的,需要根據我們的參數來進行跳轉,那麼to_url()就是用來根據我們傳入的參數來返回當前的路由地址的;我們來舉個栗子看下:from werkzeug.routing import BaseConverter from flask import Flask from flask import url_for from flask import redirect app = Flask(__name__) class RegConverter(BaseConverter): def __init__(self,url_map,regex): super(RegConverter,self).__init__(url_map) self.regex = regex app.url_map.converters['re'] = RegConverter @app.route("/goods/<re('1[234]\d{5}'):goods_id>") def goods_detail(goods_id): return 'goods_id : %s' % goods_id @app.route('/index') def index(): url = url_for('goods_detail',goods_id='1234567') # 這裏需要注意的是:要和視圖函數的參數對應,以鍵值對的方式進行賦值 return redirect(url) if __name__ == '__main__': app.run(debug=True)
我們可以看見當訪問 /index 的時候,頁面馬上發聲了跳轉,證明我們的實驗室成功的;
當然我們也可以對to_url()的處理方法進行修改;