
正文
Flask框架(二):路由与蓝图
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
一、路由
使用
route()
装饰器来把函数绑定到 URL:
@app.route('/')
def index():
return 'Index Page'
@app.route("/hello")
def view_func():
return "hello world"
但是能做的不仅仅是这些!你可以动态变化 URL 的某些部分, 还可以为一个函数指定多个规则。
变量规则
通过把 URL 的一部分标记为
<variable_name>
就可以在 URL 中添加变量。标记的 部分会作为关键字参数传递给函数。通过使用
<converter:variable_name>
,可以 选择性的加上一个转换器,为变量指定规则。请看下面的例子:
@app.route('/user/<username>')
def show_user_profile(username):
# 不声明转换器时,默认为String类型,接受任何不包含斜杠的文本
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# post_id只能是int类型
return 'Post %d' % post_id
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# path类似string,但可以包含斜杠
return 'Subpath %s' % subpath
唯一的 URL / 重定向行为
以下两条规则的不同之处在于是否使用尾部的斜杠。:
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
projects
的 URL 是中规中矩的,尾部有一个斜杠,看起来就如同一个文件夹。 访问一个没有斜杠结尾的 URL 时 Flask 会自动进行重定向,帮你在尾部加上一个斜杠。
about
的 URL 没有尾部斜杠,因此其行为表现与一个文件类似。如果访问这个 URL 时添加了尾部斜杠就会得到一个 404 错误。这样可以保持 URL 唯一,并帮助 搜索
URL 构建
url_for()
函数用于构建指定函数的 URL。它把函数名称作为第一个 参数。它可以接受任意个关键字参数,每个关键字参数对应 URL 中的变量。未知变量 将添加到 URL 中作为查询参数。
为什么不在把 URL 写死在模板中,而要使用反转函数
url_for()
动态构建?
-
反转通常比硬编码 URL 的描述性更好。
-
你可以只在一个地方改变 URL ,而不用到处乱找。
-
URL 创建会为你处理特殊字符的转义和 Unicode 数据,比较直观。
-
生产的路径总是绝对路径,可以避免相对路径产生副作用。
-
如果你的应用是放在 URL 根路径之外的地方(如在
/myapplication中,不在/中),url_for()会为你妥善处理。
例如,这里我们使用
test_request_context()
方法来尝试使用
url_for()
。
test_request_context()
告诉 Flask 正在处理一个请求,而实际上也许我们正处在交互 Python shell 之中, 并没有真正的请求。
from flask import Flask, escape, url_for
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/login')
def login():
return 'login'
@app.route('/user/<username>')
def profile(username):
return '{}\'s profile'.format(escape(username))
with app.test_request_context():
print(url_for('index'))
print(url_for('login'))
print(url_for('login', next='/'))
print(url_for('profile', username='John Doe'))
/
/login
/login?next=/
/user/John%20Doe
指定请求方式
在 Flask 中,定义路由其默认的请求方式为:
- GET
- OPTIONS(自带)
- HEAD(自带)
利用methods参数可以指定一个接口的请求方式:
@app.route("/hello1", methods=["POST"])
def view_func_1():
return "hello world 1"
@app.route("/hello2", methods=["GET", "POST"])
def view_func_2():
return "hello world 2"
二、蓝图
在一个Flask 应用项目中,如果业务视图过多,可否将以某种方式划分出的业务单元单独维护,将每个单元用到的视图、静态文件、模板文件等独立分开?例如从业务角度上,可将整个应用划分为用户模块单元、商品模块单元、订单模块单元,如何分别开发这些不同单元,并最终整合到一个项目应用中?在Django中这种需求是如何实现的?
在Django中我们是将一个个功能划分为一个个子应用去独立开发,而在Flask中,使用蓝图Blueprint来分模块组织管理。
蓝图实际可以理解为是一个存储一组视图方法的容器对象,其具有如下特点:
- 一个应用可以具有多个Blueprint
- 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/user”、“/goods”
- Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
- 在一个应用初始化时,就应该要注册需要使用的Blueprint
但是一个Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中。
使用方式
使用蓝图可以分为三个步骤
-
创建一个蓝图对象
user_bp=Blueprint('user',__name__) -
在这个蓝图对象上进行操作,注册路由,指定静态文件夹,注册模版过滤器
@user_bp.route('/')
def user_profile():
return 'user_profile' -
在应用对象上注册这个蓝图对象
app.register_blueprint(user_bp)
对于一个打算包含多个文件的蓝图,通常将创建蓝图对象放到Python包的
__init__.py
文件中
--------- project # 工程目录
|------ main.py # 启动文件
|------ user #用户蓝图
| |--- __init__.py # 此处创建蓝图对象
| |--- passport.py
| |--- profile.py
| |--- ...
|
|------ goods # 商品蓝图
| |--- __init__.py
| |--- ...
|...
扩展用法
1 指定蓝图的url前缀
在应用中注册蓝图时使用
url_prefix
参数指定
app.register_blueprint(user_bp, url_prefix='/user')
app.register_blueprint(goods_bp, url_prefix='/goods')
2 蓝图内部静态文件
和应用对象不同,蓝图对象创建时不会默认注册静态目录的路由。需要我们在 创建时指定 static_folder 参数。
下面的示例将蓝图所在目录下的static_admin目录设置为静态目录
admin = Blueprint("admin",__name__,static_folder='static_admin')
app.register_blueprint(admin,url_prefix='/admin')
现在就可以使用
/admin/static_admin/<filename>
访问
static_admin
目录下的静态文件了。
也可通过
static_url_path
改变访问路径
admin = Blueprint("admin",__name__,static_folder='static_admin',static_url_path='/lib')
app.register_blueprint(admin,url_prefix='/admin')
3 蓝图内部模板目录
蓝图对象默认的模板目录为系统的模版目录,可以在创建蓝图对象时使用 template_folder 关键字参数设置模板目录
admin = Blueprint('admin',__name__,template_folder='my_templates')







