西北有高楼,上与浮云齐。--- 西北望高楼
本章主要内容:讲一下初始化一个项目,以及项目的层级结构该怎么设计。
上面说过,我们将会通过一个 restful api 项目来学习,下面我将会手把手教大家怎么初始化一个 Flask 项目。
作者使用环境说明:
Python版本:3.8.10 开发工具:Pycharm (自由选择即可) 项目名称:restful_api
创建项目
1. 创建项目根目录并初始化环境
我以终端命令方式展示一下创建目录的过程:
# 创建项目根目录
# leou @ leoumac in ~/Desktop/flask [11:36:57]
$ mkdir restful_api
# leou @ leoumac in ~/Desktop/flask [11:37:06]
$ cd restful_api
# 初始化Python版本环境
# leou @ leoumac in ~/Desktop/flask/restful_api [11:37:11]
$ pyenv local 3.8.10
# 创建项目虚拟环境
# leou @ leoumac in ~/Desktop/flask/restful_api [11:37:30]
$ python -m venv env
# 激活项目虚拟环境
# leou @ leoumac in ~/Desktop/flask/restful_api [11:37:50]
$ source env/bin/activate
# 安装flask库
(env)
# leou @ leoumac in ~/Desktop/flask/restful_api [11:37:59]
$ pip install flask
# 查看当前依赖的第三方库
(env)
# leou @ leoumac in ~/Desktop/flask/restful_api [11:38:18]
$ pip list
Package Version
------------------ -------
click 8.1.3
Flask 2.2.0
importlib-metadata 4.12.0
itsdangerous 2.1.2
Jinja2 3.1.2
MarkupSafe 2.1.1
pip 21.1.1
setuptools 56.0.0
Werkzeug 2.2.1
zipp 3.8.1
# 将第三方库依赖列表导入到requirements.txt文件
# 导入后方便部署安装第三方库(通过pip install -r requirements.txt 批量安装)
(env)
# leou @ leoumac in ~/Desktop/flask/restful_api [11:38:23]
$ pip freeze > requirements.txt
(env)
# leou @ leoumac in ~/Desktop/flask/restful_api [11:38:55]
$ cat requirements.txt
click==8.1.3
Flask==2.2.0
importlib-metadata==4.12.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
Werkzeug==2.2.1
zipp==3.8.1
(env)
按照上面的步骤,执行完毕之后,我们的环境就已经初始化完成。
2. 创建Flask App
下面的步骤,我们将会把项目运行起来。创建 Flask App的方式,我使用工厂模式来创建,如下:
- 第一步: 创建
Python Package名字为app; - 第二步: 创建启动文件
run.py;
创建完成之后,当前其结构如下:
.
└── restful_api
├── app
│ └── __init__.py
├── env
├── requirements.txt
└── run.py
然后需要生成Flask App,app/__init__.py代码如下:
# app/__init__.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask
def create_app():
"""工厂模式初始化app"""
app = Flask(__name__)
return app
项目启动文件run.py代码如下:
# run.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run()
3. 让项目跑起来
通过上面的操作之后,其实我们的项目已经可以跑起来了。执行下面的命令:
# 终端运行 python run.py
(env)
# leou @ LeouMac in ~/Desktop/flask/restful_api [15:38:36]
$ python run.py
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Serving Flask app 'app'
* Debug mode: off
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
出现上面的情况,说明我们的项目已经运行成功。截止到目前我们已经成功的创建了一个Flask项目,并且能让它正常的运行起来。
4. 引入自定义配置
细心的朋友可能已经发现,上面我们运行之后,出现了一个警告,意思是这是一个开发阶段的服务,不要用在生产环境的部署上,关于WSGI我们后面讨论,暂时不用考虑。那么在开发环境下,我们常常希望在运行时看到错误信息,该怎么做呢?那就需要开启Debug模式,开启之后,我们不仅能看到运行时的错误,在变动代码之后,项目还会主动重新加载运行,而不用手动重新运行。(还有更多的DEBUG小妙招,去研究一下吧)
我们可以直接更改run.py文件,设置运行参数,而这里参数的设置,为了方便后面增加其他配置参数,我们通过引入自定义配置的方式来开启Debug模式。
- 第一步: 在包
app下创建Python Package名字为config;- 第二步: 创建开发环境配置文件
dev.py;
创建完成之后,当前其结构如下:
.
├── app
│ ├── __init__.py
│ └── config
│ ├── __init__.py
│ └── dev.py
├── env
├── requirements.txt
└── run.py
其中,app/config/dev.py代码如下:
# app/config/dev.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
# 以DEBUG模式运行
DEBUG = True
其中,app/config/__init__.py代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from . import dev
config_dict = {
'dev': dev
}
然后把工厂模式的app/__init__.py下的create_app函数更改一下,支持配置参数:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from flask import Flask
from app.config import config_dict
def create_app(config_name):
"""工厂模式初始化app"""
app = Flask(__name__)
# 加载配置,其方式有多重,感兴趣的可以自己读源码看看
app.config.from_object(config_dict[config_name])
return app
项目启动文件run.py代码更新如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from app import create_app
app = create_app(
config_name="dev"
)
if __name__ == '__main__':
app.run(
debug=app.config.get("DEBUG")
)
这样,我们就可以重新运行了:
# leou @ LeouMac in ~/Desktop/flask/restful_api [17:18:36] C:1
$ python run.py
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Serving Flask app 'app'
* Debug mode: on
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 129-075-722
上面我们说了那么多,只是把Flask项目运行起来,接下来我们就看看怎么添加第一个API吧。
第一个API
当下,大部分项目都是前后端分离,所以上面说过,我们的项目是一个restful api项目,也就是说,我们的重点就是写一个后端API项目。项目运行起来之后,我们访问上面的地址http://127.0.0.1:5000会出现404 Not Found返回,是因为我们的项目没有做任何的路由配置。接下来,我们就写一个接口,并配置上路由。
接口路由:/api/net/check 接口说明: 健康检查
新建接口文件
步骤:
1. 在包app下新增名为api的包,即app/api,代表着api;
2. 在包app/api下新增名为check的包,即app/api/check,存放健康检查相关的路由;
3. 在包app/api/check下新增名为check.py的文件,存放check相关的接口;
当前目录结构如下:
.
├── app
│ ├── __init__.py
│ ├── api
│ │ ├── __init__.py
│ │ └── check
│ └── config
│ ├── __init__.py
│ └── dev.py
├── env
├── requirements.txt
└── run.py
创建接口
Flask用来管理不同的路由方式,使用的就是蓝图 Blueprint,通过蓝图。我们可以将同模块下不同功能的代码函数化注册到蓝图上,最后将蓝图注册到应用,从而能够方便的将不同逻辑的代码分开处理,最终实现模块化。
话不多说,先看代码。
- 编写
app/api/check/check.py文件,如下:
# app/api/check/check.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from flask import Blueprint, jsonify
check_api_bp = Blueprint('check_bp_api', __name__, template_folder='templates')
@check_api_bp.route('/net/check', methods=['GET'])
def net_check():
"""服务健康检查"""
data = {
"success": True,
"error": {
"code": 20000,
"message": "请求成功"
}
}
return jsonify(data)
这一部分,我们实现了一个健康检查的接口,创建一个蓝图
check_api_bp,@check_api_bp.route('/net/check', methods=['GET'])是通过装饰器的方式将函数net_check()注册到该蓝图上,成为一个路由,其路径规则为:/net/check(URL路径的后缀部分),请求方法是GET,更详细的介绍看类的源码。该路由返回的是json数据。
- 编写
app/api/__init__.py文件,如下:
# app/api/__init__.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from .check import check
blueprints = [
(check.check_api_bp, '/api'),
]
这一部分其实是将
api下所有的蓝图集中起来的一个方式,方便把蓝图注册到Flask App中。blueprints是蓝图列表,里面的元组(check.check_api_bp, '/api')含义是 (蓝图, 蓝图前缀),其中蓝图前缀和上面的路径规则(后缀)共同组成了一个路由Path。
- 编写
app/__init__.py文件,如下:
# app/__init__.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from flask import Flask
from app.config import config_dict
def create_app(config_name):
"""工厂模式初始化app"""
app = Flask(__name__)
app.config.from_object(config_dict[config_name])
from .api import blueprints as api_bp
for bp, url_prefix in api_bp:
app.register_blueprint(bp, url_prefix=url_prefix)
return app
这一部分是把蓝图注册到Flask App中的方式。我们在创建App之后做这一部分动作。
当然集成在create_app()函数里不太美,我们可以把它提出来:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Create by: leou at 2022-08-03
from flask import Flask
from app.config import config_dict
def create_app(config_name):
"""工厂模式初始化app"""
app = Flask(__name__)
app.config.from_object(config_dict[config_name])
register_blueprints(app=app)
return app
def register_blueprints(app):
"""注册蓝图到Flask App"""
from .api import blueprints as api_bp
for bp, url_prefix in api_bp:
app.register_blueprint(bp, url_prefix=url_prefix)
这样就好看多了。
- 重新启动项目
执行python run.py启动项目,然后访问http://127.0.0.1:5000/api/net/check接口,正常情况下可以得到:
{
"error": {
"code": 20000,
"message": "请求成功"
},
"success": true
}
总结
到这里为止,我们已经完成了含有一个接口功能的Flask项目,项目层级结构如下:
.
├── app
│ ├── __init__.py
│ ├── api
│ │ ├── __init__.py
│ │ └── check
│ └── config
│ ├── __init__.py
│ └── dev.py
├── env
├── requirements.txt
└── run.py
回顾一下我们本章节的功能,分别是:
- 创建了一个项目,并初始化运行环境;
- 通过工厂模式实现了Flask App的创建以及配置加载;
- 实现了第一个简单的接口;
通过上面的步骤,我们最终能成功的运行项目,并且拿到接口的返回值。基本上,你也能了解到一个Flask App是如何运行起来的。后面的章节,我们会逐步增加不同的模块、功能,带你走进真正的Flask世界。