让咱们先来看一个简单的例子,假设有下面这样一个蓝图(是关于用户主页的):html
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前缀。让咱们把蓝图定义改为这样:flask
profile = Blueprint('profile', __name__, url_prefix='/<user_url_slug>')
或者在注册到app时指定: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
实际应用中,咱们会发现,若使用url_for
来生成URL,会出现参数不足的错误,这是为何呢?这是由于咱们把user_url_slug
弹出了,url_for
工做时须要使用这个值,可是这个时候这个值找不到了,所以咱们要把user_url_slug
值从新压入:spa
profile.url_defaults def add_user_url_slug(endpoint, values): values.setdefault('user_url_slug', g.user_url_slug)
完整例子:code
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')