首页 > 技术文章 > 使用Flask2.0创建一个简单的项目

blueberry-mint 2021-09-03 15:26 原文

Flask2.0重要改动

据JetBrains Python开发者社区调查,Flask是近年来最常用的Python Web开发框架之一。Flask2.0.0于2021年5月份发布,共推出了三十多个版本变更,主要变更如下:

三大核心特性

  • 嵌套蓝图
  • 异步视图
  • 快捷路由装饰器

其他重要变化

  • 不再支持Python2和Python3.5
  • 新增了Type hinting,有助于IDE自动补全
  • 支持从任意文件加载器导入配置(导入方法为Config.from_file()
  • 优化浏览器缓存控制,静态文件变动后,重启应用会立即更新资源(不再需要手动清缓存)
  • Werkzeug的multipart解析性能提高了15倍
  • jsonify支持序列化decimal.Decimal 格式的数据(该改动在Flask2.0.2版本添加)

安装

本文使用Python3.9(部分特性需要3.9以上版本支持)

pip install -U flask

若是想用Flask2.0的异步功能,则需要安装额外依赖(主要是asgiref包)

pip install -U flask[async]

三大核心特性讲解

上面我列出了Flask2.0新增的三大核心特性,接下来我会通过代码来说明这三大特性的特点和使用方法,并尝试根据这三大特性来编写一个简单的应用。

嵌套蓝图

Flask使用蓝图Blueprint对程序进行模块化处理。一个大型项目通常都会使用蓝图来规划不同的模块,而嵌套蓝图的作用就是可以更细地去划分管理不同的模块。

一个应用可以注册多个蓝图,而现在蓝图也可以注册多个子蓝图(子蓝图还可以注册孙子蓝图,可以嵌套很多层,支持无限嵌套),对项目进行多层模块化组织。

app = Flask(__name__)  # 创建一个应用
a = Blueprint('a', __name__)  # 创建父蓝图
b = Blueprint('b', __name__)  # 创建子蓝图
a.register_blueprint(b)  # 将子蓝图注册到父蓝图上
app.register_blueprint(a)  # 将父蓝图注册到应用上

上面例子只是简单示范嵌套蓝图的使用,实际开发中一般不会将应用和蓝图写到同一个文件内。

异步视图

Flask2.0加入了基本的async/await支持(目前只是基于asgiref来实现异步),因此我们可以自己去定义异步视图。

异步视图有很多优点,比如能够在不使用Python线程的情况下为数百个连接提供服务,允许使用慢速流、长轮询和其他的响应类型等等。

import asyncio
from flask import Flask

app = Flask(__name__)


@app.route('/')
async def hello():
    await asyncio.sleep(1)
    return 'hello flask'


if __name__ == '__main__':
    app.run()

快捷路由装饰器

新增了以下路由装饰器:

  • app.get()
  • app.post()
  • app.delete()
  • app.put()
  • app.patch()

上面的路由装饰器对应之前的app.route()装饰器,如app.post()相当于app.route(methods=['POST'])。需要注意的是,这些快捷路由装饰器只能处理单个方法类型的请求,如果需要处理多种方法类型的请求,请用app.route()装饰器。

from flask import Flask

app = Flask(__name__)


@app.post('/hello')  # 快捷路由装饰器
def hello():
    return 'Hello Flask'


@app.route('/hello2', methods=['GET', 'POST'])  # 多种请求类型
def hello2():
    return 'Hello Flask2'


if __name__ == '__main__':
    app.run()

创建一个简单的项目

在了解了Flask2.0的一些新功能和新特性后,我们来尝试使用这些新特性创建一个简单的项目

该项目上创建一个应用,应用上注册了两个蓝图,分别为v1v2(代表两个不同的版本),v1蓝图和v2蓝图上分别注册了子蓝图adminuser,v1版本的视图函数使用以往的写法,v2版本的视图函数使用新的特性,以便大家进行对比。

项目的目录结构如下

flask2
	/app
		/v1
			__init__.py
			admin.py
			user.py
		/v2
			__init__.py
			admin.py
			user.py
		__init__.py
	manager.py

manager.py文件用于启动我们的Web服务

from flask import Flask
from app import v1, v2

app = Flask(__name__)  # 创建Flask的主app
app.register_blueprint(v1.bp)  # 注册蓝图
app.register_blueprint(v2.bp)


@app.route('/')
def index():
    return 'Hello World'


if __name__ == '__main__':
    app.run(debug=True)

/app/v1/__init__.py,该文件主要用于加载项目包时创建父蓝图和注册子蓝图

from flask import Blueprint
from app.v1 import admin, user

bp = Blueprint('v1', __name__, url_prefix='/v1')  # 创建父蓝图v1

bp.register_blueprint(admin.api)  # 注册子蓝图admin
bp.register_blueprint(user.api)  # 注册子蓝图user


@bp.route('')
def index():
    """父蓝图视图函数"""
    return 'here is v1.'

/app/v1/admin.py

from flask import Blueprint

api = Blueprint('admin', __name__, url_prefix='/admin')  # 创建一个蓝图


@api.route('')
def index():
    return 'here is admin v1.'


@api.route('/hello', methods=['POST'])
def hello():
    return 'hello admin v1'

/app/v1/user.py

from flask import Blueprint

api = Blueprint('user', __name__, url_prefix='/user')  # 创建一个蓝图


@api.route('')
def index():
    return 'here is user v1.'


@api.route('/hello', methods=['GET', 'POST']) # 多种请求类型
def hello():
    return 'hello user v1.'

/app/v2/__init__.py

from flask import Blueprint
from app.v2 import admin, user

bp = Blueprint('v2', __name__, url_prefix='/v2')  # 创建父蓝图v2

bp.register_blueprint(admin.api)  # 注册子蓝图admin
bp.register_blueprint(user.api)  # 注册子蓝图user


@bp.route('')
def index():
    """父蓝图视图函数"""
    return 'here is v2.'

/app/v2/admin.py

import asyncio

from flask import Blueprint

api = Blueprint('admin', __name__, url_prefix='/admin')  # 创建一个蓝图


@api.get('')  # 快捷路由装饰器
def index():
    return 'here is admin v2.'


@api.post('/hello')
async def hello():
    """异步视图"""
    await asyncio.sleep(1)
    return 'hello admin v2.'

/app/v2/user.py

import asyncio

from flask import Blueprint

api = Blueprint('user', __name__, url_prefix='/user')  # 创建一个蓝图


@api.get('')
def index():
    return 'here is user v2.'


@api.post('/hello')
async def hello():
    await asyncio.sleep(1)
    return 'hello user v2.'

项目代码我放到我的Github上,有需要的话可以去上面取。

代码编写完后运行manager.py文件启动项目,项目url为 http://localhost:5000

可以使用python或者Postman软件来发送相关的请求,如发送一个GET请求到 http://localhost:5000/v1/user ,或者发送一个POST请求到 http://localhost:5000/v2/user/hello ,会返回相关的数据。(如果返回的结果是404或405,则注意是否url或者请求方法错了)

以上就是Flask2.0的新特性介绍,如果想学习更多关于Flask的知识点,可以去Flask官方文档中查阅。

推荐阅读