在Flask藍圖中使用動態URL前綴
1.引入:看下面代碼
from flask import Blueprint, render_template profile = Blueprint('profile', __name__) @profile.route('/<user_url_slug>') def timeline(user_url_slug): # Do some stuff return render_template('profile/timeline.html') @profile.route('/<user_url_slug>/photos') def photos(user_url_slug): # Do some stuff return render_template('profile/photos.html') @profile.route('/<user_url_slug>/about') def about(user_url_slug): # Do some stuff return render_template('profile/about.html')
從上面可以看出,所有的路由都是以user_url_slug開頭的,
若這樣寫代碼的話,會增加代碼的復雜性、降低可維護性。為了解決這個問題,我們可以在藍圖中定義動態的url前綴。
讓我們把藍圖定義改成這樣:
profile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>')
或者注冊到app時指定:
app.register_blueprint(profile, url_prefix='/<user_url_slug>')
現在,把路由改成精簡的形式:
@profile.url_value_preprocessor def pull_user_url_slug(endpoint, values): g.user_url_slug = values.pop('user_url_slug') query = User.query.filter_by(url_slug=g.user_url_slug) g.profile_owner = query.first_or_404() @profile.route('/') def timeline(): return render_template('profile/timeline.html') @profile.route('/photos') def photos(): return render_template('profile/photos.html') @profile.route('/about') def about(): return render_template('profile/about.html')
url_value_preprocessor
裝飾器用於把user_url_slug
值彈出,並保存到g
變量中,這樣就不會傳遞給路由函數。
實際應用中,我們會發現,若使用url_for
來生成URL,會出現參數不足的錯誤,這是為什么呢?這是因為我們把user_url_slug
彈出了,url_for
工作時需要使用這個值,但是這個時候這個值找不到了,因此我們要把user_url_slug
值重新壓入:
@profile.url_defaults def add_user_url_slug(endpoint, values): values.setdefault('user_url_slug', g.user_url_slug)
完整例子:
from flask import Blueprint, render_template profile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>') @profile.url_defaults def add_user_url_slug(endpoint, values): values.setdefault('user_url_slug', g.user_url_slug) @profile.url_value_preprocessor def pull_user_url_slug(endpoint, values): g.user_url_slug = values.pop('user_url_slug') query = User.query.filter_by(url_slug=g.user_url_slug) g.profile_owner = query.first_or_404() @profile.route('/') def timeline(): return render_template('profile/timeline.html') @profile.route('/photos') def photos(): return render_template('profile/photos.html') @profile.route('/about') def about(): return render_template('profile/about.html')