本文项目对应地存储库: https://github.com/Farmer-chong/HelloAPIFlask

最近正值毕业阶段,相信许多人的毕业设计都无不例外的选择了Web相关的内容,毕竟这个比较容易实现。我发现许多人都出于从众心理无不例外的使用了Spring全家桶,Spring有着很庞大的生态、久远的历史以及很丰富的社区资料,这使得它被许多从业者使用。但也正是这些优势导致它对新手或者快速上手开发变得十分不好,再加之国内的毒瘤技术社区等原因,使得一个小问题往往需要花费大量的时间来排除错误的答案。

相比于繁重、学习成本较高的Spring,Flask其简单的语法可以是我们快速的上手完成(应对)毕设这一类学业任务, 因此本文仅停留在 能用 阶段, 更多底层原理需要读者自行了解(这里推荐一下李大的狗书《Flask Web 开发实战 》) 另外出于为社区做贡献等情怀原因也是写这一系列的初衷。

系列文章

  1. 后端系列: 基本简介与Hello APIFlask! (一)

写在前面

本文默认使用Windows进行开发,Linux/macOS会特别说明

相比于传统的后端渲染模板架构,本文采用目前主流的前后端分离结构

对于前后端分离,服务端只需要提供API接口来处理请求。简单的来说就是前端不再局限于浏览器,还可以是app、小程序亦或者是爬虫程序。对后端而言,我们不再渲染html返回给前端,而是与前端共同约定一个数据格式进行交互。

如果读者的思想还停留在具体的浏览器中,那需要读者打开思维的局限来理解。无论是传统的后端渲染还是前后端分离,其本质都是操作 HTTP报文

许多人此时会有个疑问:为什么一会儿Flask一会APIFlask的,这两者有什么关系?

先来简单的说一下,Flask是一个十分流行的 Python Web 框架。而APIFlask则是基于Flask框架针对 Web API开发的特点二次开发的框架,这是一个针对API而生的框架(或者具体点前后端分离)。如果读者有Java开发经验,可以理解类似于SpringSpring Boot的关系。

扩展阅读:

  1. APIFlask是什么
  2. Flask、APIFlask与其他Web框架之间的关系

因为APIFlask是一个Flask的扩展补充框架,因此它大部分都是与Flask保持一致的,你甚至可以把APIFlask当成Flask来写(当然这并不推荐)。因此对Flask有经验的读者许多内容是可以跳过阅读的,我甚至更推荐你去阅读 APIFlask的官方文档

初识APIFlask(Hello APIFlask)

废话放在后面说,作为快速上手教程,理所应当地先来个Hello World感受一下Flask的魅力,作为一篇保姆级教程下面就让从pip这个包管理器开始安装一下APIFlask吧(默认安装好python及其包管理器)

快速开始

小白的话就直接运行下面这条命令即可

1
pip install apiflask # Linux环境用pip3

当然本人还是强烈建议使用虚拟环境哈。细节就不多赘述了,下面开始写一个Hello World吧:

hello/app.py
1
2
3
4
5
6
from apiflask import APIFlask
app = APIFlask(__name__)

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

哪怕你没有开发经验,单纯的看单词也许已经猜到它是做什么了,下面就来一步步的分解这个程序。

创建应用实例(application 对象)

我们使用pip安装apiflask,其实也就是下载了一个叫apiflask的包。因此我们可以通过apiflask包的构造文件导入开发的类和函数。我们一开始从apiflask包导入APIFlask类,实例化这个类,就得到了我们的程序实例app:

1
2
from apiflask import APIFlask
app = APIFlask(__name__)

传入apiflask的第一个参数是模块或者包名词,这里使用Python的特殊变量__name__

注册路由

首先对于很多初学者来说都会有这么一个问题:路由是什么?

回答这个问题之前我们先来看看一个传统的Web应用,客户端和服务器上的程序是如何交互的:

  1. 用户在浏览器输入URL访问某个资源
  2. APIFlask接收用户请求并分析请求的URL
  3. APIFlask为这个URL找到对应的处理函数
  4. 执行函数并生成响应,然后返回给浏览器
  5. 浏览器接收并解析响应

而我们现在要做前后端分离,整个流程和上面是一致的,但客户端具体的对象则从浏览器变成了一段发起 http 请求的代码,以网页前后端分离为例稍微完善一下如下:

  1. 前端使用AJAX向后端发起请求
  2. APIFlask接收请求并分析请求的URL
  3. APIFlask为这个URL找到对应的处理函数
  4. 执行函数并生成 HTTP 响应
  5. AJAX接收响应
  6. 根据后续的业务代码进行页面的修改

⚠⚠注意⚠⚠ 这里的 AJAX 是指 Asynchronous JavaScript + XML(异步JavaScript和XML) 这是一个技术名词,读者需要注意与较多人熟知的jQuery库的ajax方法进行区分!!!
简单的来讲,jQueryajaxAJAX 技术的一个实现,有着许多同类的替代品,比如axios。由于笔者见过太多的人将两者混淆,故在此着重强调。

这些步骤中,大部分都是由APIFlask完成,我们只需要将处理函数与URL对应起来。只需在函数添加app.route()装饰器,并传入URL规则作为参数,就可以让URL与函数建立关系。这个过程我们称为注册路由(route),路由复制管理URL和函数之间的映射,而这个函数则被称为视图函数(view function)。

1. 绑定多个URL

一个视图函数可以绑定多个URL,具体就像下面这段代码:

1
2
3
4
@app.route('/')
@app.route('/hello')
def index():
return 'Hello apiflask!'

2. 动态URL

我们还可以在URL规则中添加变量部分, 使用<变量名>的形式表示。APIFlask处理请求时会把变量传入视图函数,代码如下:

1
2
3
@app.route('/hello/<name>')
def hello(name:str):
return f'Hello {name}!'

如果URL变量中包含变量,但如果又要适配没有变量的情况,比如与多个URL配合起来使用,那么我们可以给一个默认值:

1
2
3
4
@app.route('/hello', defaults={'name': 'farmer'})
@app.route('/hello/<name>')
def say_hello(name:str):
return f'Hello {name}!'

启动开发服务器

Flask内置了一个开发服务器(由依赖包Werkzeug)提供,足够在开发和测试阶段使用,而APIFlask是基于Flask二次开发的,因此我们一样可以使用。

在生产环境需要使用性能够好的生产服务器,以提升安全和性能,具体更多内容移步到《Flask Web 开发实战 》

在项目的根目录下,输入下面这条命令:

1
flask run

然后我们会看到如下输出:

1
2
3
4
5
6
* Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

这时候我们在浏览器访问这个URL,会看到这样显示:

同理,其他URL自行替换即可得到相应的结果。但由于我们开发的是前后端分离架构,后端只负责提供API进行访问,除了基本的GET请求外还有大量其他请求报文。因为浏览器的调试无疑是不够的,为此APIFlask提供了交互式API文档(基于Swagger UI and Redoc)

要进入这个交互式API文档,默认的方式是访问/docs路由,为此我们重新在浏览器访问: http://127.0.0.1:5000/docs,即可看到下面的这个页面:

后续都会基于该API文档进行演示,当然你也可以访问: http://127.0.0.1:5000/redoc 查看基于Redoc生成的API文档。

需要注意,网上许多教程都是通过app.run()形式来运行开发服务器的,这种方式其实是旧的启动方式,已经过时了目前已不推荐使用(deprecated)。

Flask通过依赖包Click内置了一个CLI(Command Line Interface, 命令行交互界面)系统。当我们安装Flask后,会自动添加一个flask命令脚本,我们可以通过flask命令执行内置命令、扩展插件的命令与我们自定义的命令。其中,flask run命令用来启动开发服务器。

此外,你还可以执行flask --help查看所有命令,这些命令都需要在项目的根目录执行。

自动发现程序实例

上面启动开发服务器我们使用了flask run来启动,这就不禁让人好奇,Flask是如何找到程序的?

其实这个问题是因为Flask会自动探测程序实例,一般来说,在执行flask run命令运行程序前,我们需要提供程序实例所在模块的位置,而自动探测是按照下面这些规则:

  1. 从当前目录寻找app.pywsgi.py模块,并从中寻找名为appapplication的程序实例
  2. 从环境变量FLASK_APP对应的模块名/导入路径寻找名为appapplication的程序实例

因为我们上面的程序代码文件名为app.py,所以flask run命令会自动在其中寻找应用实例。如果你的程序文件名是其他名称,比如hello_apiflask.py,那么需要设置环境变量FLASK_APP,将包含程序实例的模块名赋值给这个变量。命令如下:

1
set FLASK_APP=hello_apiflask

Linux或macOS系统使用export命令:

1
export FLASK_APP=hello_apiflask

管理环境变量

FLASK的自动发现程序实例机制还有第三条规则: 如果安装了python-dotenv,那么在使用flask run或其他命令时会自动使用它从.flaskenv文件和.env文件中加载环境变量。

安装python-dotenv包命令如下:

1
pip install python-dotenv # Linux环境用pip3

除了管理自动发现程序实例外,我们还可以用来管理程序需要的环境变量。我们在项目根目录下分别创建两个文件:.env.flaskenv,其中.flaskenv用来管理和Flask相关的公开环境变量。而.env文件则用来管理包含敏感信息的环境变量。

.env包含敏感信息,除非是私有项目,否则绝对不能提交到Git仓库中

扩展阅读

为什么写扩展阅读,扩展阅读的作用?

扩展阅读模块主要是对上面的内容进行补充,内容并非必读内容并不会影响程序的运行,更多是补充开发相关各方面的知识内容。

配置热更新(重载器)

开发环境(development environment)和生产环境(production environment)。根据运行环境的不同,Flask程序、扩展以及其他程序会改变相应的行为和设置。为了区分运行环境,Flask提供了一个FLASK_ENV环境变量用来设置环境,默认为production(生产)。在开发时我们可以将其设置为development,这会开启所有支持开发的特性,为了方便管理我们还可以将其写入到.flaskenv文件中:

./.flaskenv
1
FLASK_ENV=development

现在启动程序,你会看到下面的输出提示:

1
2
3
4
5
6
7
(env) E:\Github\HelloAPIFlask\demos\hello>flask run
* Environment: development
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 500-487-380
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

在开发环境下,调试模式(Debug Mode)将被开启,这时执行flask run启动程序会自动激活Werkzeug内置的调试器(debugger)和重载器(reloader),他们会为开发带来很大的帮助。

如果你想单独控制调试模式开关,可以通过FLASK_DEBUG环境变量来设置,设为1为开启,设为0则关闭,不过通常不推荐手动设置这个值

创建虚拟环境

在 Python 中,虚拟环境(virtual enviroment)就是隔离的 Python 解释器环境。通过创建虚拟环境,你可以拥有一个独立的 Python 解释器环境。这样做的好处是可以为每一个项目创建独立的 Python 解释器环境,因为不同的项目经常会依赖不同版本的库或Python版本。使用虚拟环境可以保持全局 Python 解释器环境的干净,避免包和版本的混乱,并且可以方便地区分和记录每个项目的依赖,以便在新环境下复现依赖环境。

虚拟环境通常使用Virtualenv来创建,除此之外还有PipenvPDM等诸多环境管理工具。简单起见,我们使用Python3自带的工具来创建虚拟环境,首先确保我们当前工作目录在项目的根目录,然后使用python3 -m venv env命令为当前项目创建虚拟环境:

Windows
1
python -m venv env
Linux
1
python3 -m venv env

提示: Windows用户可直接复制,但Linux系统大多存在python2与python3,Linux用户需要注意这点

这会在当前目录创建一个名为env的文件夹(命令最后一个选项为文件夹名),其中包含隔离的Python解释器环境。

激活虚拟环境

在创建虚拟环境后,我们还需要载入(激活)这个环境,接下来使用.\env\Script\active来激活虚拟环境:

1
2
3
E:\Github\HelloAPIFlask>.\env\Scripts\activate

(env) E:\Github\HelloAPIFlask>

Linux环境使用source命令来激活:

1
2
3
farmer@farmer-ubuntu:~/HelloAPIFlask$ source ./env/bin/activate

(env) farmer@farmer-ubuntu:~/HelloAPIFlask$ source ./env/bin/activate

可以看到虚拟环境激活后命令行前面多了一个虚拟环境的标识,这就表示虚拟环境激活啦!使用pip list我们可以看到该环境是一个全新的环境。

更多启动项

  1. 使服务器外部可见
    我们上面启动的Web服务器默认是对外不可见的,我们可以通过--host选项将主机地址改为0.0.0.0使其对外部可见:
    1
    flask run --host=0.0.0.0

需要注意这里的外部是指你计算机外部,并不是指公网。一般个人的电脑是没有公网IP(公有地址),所以此时你的程序只能被局域网内的其他用户通过你电脑的IP(内网)进行访问。

  1. 改变默认端口

Flask提供的Web服务器默认监听5000端口,你可以通过--port选项进行更改:

1
flask run --port=2333

此时会监听来自2333端口的请求,对应的程序网址也变成了 http://127.0.0.1:2333/。

彩蛋

这一切开始于2010年4月1日,Armin Ronacher在网上发布了一篇关于”下一代 Python 微框架”的介绍文章,文章里称这个 Denied 框架不依赖 Python 标准库,只需要复制一份 deny.py 放到你的项目文件夹就可以开始编程。随着一本正经的介绍、名人推荐语、示例代码和演示视频,这个”虚假“的项目让不少人信以为真。5天后 Flask 就从这么一个愚人节玩笑诞生了。

同样的,APIFlask这个框架开始于 2021年4月1日,不知道是机缘巧合还是Grey Li有意为之的一个小玩笑,APIFlaskFlask均诞生于4月1日这一天。🎉🚀✨

在与Grey Li求证后得知两者选择同一天发布是有意为之的!!😄