首页 > 技术文章 > Flask框架(二):路由与蓝图

biyenanhai 2020-08-03 23:33 原文

一、路由

使用 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() 动态构建?

  1. 反转通常比硬编码 URL 的描述性更好。

  2. 你可以只在一个地方改变 URL ,而不用到处乱找。

  3. URL 创建会为你处理特殊字符的转义和 Unicode 数据,比较直观。

  4. 生产的路径总是绝对路径,可以避免相对路径产生副作用。

  5. 如果你的应用是放在 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并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中。

使用方式

使用蓝图可以分为三个步骤

  1. 创建一个蓝图对象

     user_bp=Blueprint('user',__name__)
  2. 在这个蓝图对象上进行操作,注册路由,指定静态文件夹,注册模版过滤器

     @user_bp.route('/')
     def user_profile():
         return 'user_profile'
  3. 在应用对象上注册这个蓝图对象

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

 

推荐阅读