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')