Flask学习(2)-初始化项目

225 阅读6分钟

西北有高楼,上与浮云齐。--- 西北望高楼

本章主要内容:讲一下初始化一个项目,以及项目的层级结构该怎么设计。

上面说过,我们将会通过一个 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 Appapp/__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

回顾一下我们本章节的功能,分别是:

  1. 创建了一个项目,并初始化运行环境;
  2. 通过工厂模式实现了Flask App的创建以及配置加载;
  3. 实现了第一个简单的接口;

通过上面的步骤,我们最终能成功的运行项目,并且拿到接口的返回值。基本上,你也能了解到一个Flask App是如何运行起来的。后面的章节,我们会逐步增加不同的模块、功能,带你走进真正的Flask世界。