使用 Flask + Flask RESTful 快速搭建 API 服务

2023年 7月 13日 24.4k 0

简介

Flask 是 Python 社区中开发 Web 应用最火热的框架之一,不同于 Django 陡峭的学习曲线,个人感觉 Flask 非常好上手,且社区生态丰富,有很多成熟的扩展可以拿来直接安装使用。 Flask 框架自身集成了基于 Jinja 的模板语言,使其可以完成前后端的所有开发,但现在大部分的 Web 应用都是前后端分离,所以本文将使用 Flask RESTful 扩展实现一个纯后端的 API 服务。 通过本文可以学习到以下内容:

  • 使用 Flask + Flask RESTful 搭建 API 应用并使用 Blueprint(蓝图) 管理 API;
  • 使用 Flask-SQLAlchemy 扩展实现 ORM 操作 MySQL 数据库;
  • 基于 JWT 验证实现注册、登录以及登出接口;
  • 实现一个最基本的列表获取接口;
  • 解决跨域问题;
  • 使用 Docker 部署该应用。

在正式开始之前,请确保你已经安装了 Python,并且对 Python 有一定了解。

初始化项目

首先我们新建一个空文件夹,作为项目的根目录。进入到项目根目录后创建一个虚拟环境:

# MacOS/Linux
mkdir myproject
cd myproject
python3 -m venv .venv
​
# Windows
mkdir myproject
cd myproject
py -3 -m venv .venv

激活虚拟环境

# MacOS/Linux
. .venv/bin/activate
# Windows
.venv\Scripts\activate

安装 Flask、Flask RESTful 以及 python-dotenv,最后一个包用来获取我们在项目中定义的环境变量。

pip install Flask flask-restful python-dotenv

按照惯例,我们先简单实现一个接口,验证下我们最基础的包是否安装完成。 首先在项目根目录下新建一个 app 文件夹,在 app 下新建一个 __init__.py 文件,在这个文件中,我们定义一个测试用的接口。

from flask import Flask
from flask_restful import Resource, Api
​
​
app = Flask(__name__)
api = Api(app)
​
class HelloWorld(Resource):
    def get(self):
        return {'hello': 'world'}
​
api.add_resource(HelloWorld, '/')

我们先引入了 Flask 和 flask_restful 中的 ResourceApi,然后我们使用 Flask() 初始化一个 Flask 应用实例赋值给 app,传入的 __name__ 则是模块名 "app",然后再使用 Api(app) 初始化一个 flask_restful 实例赋值给 api。 接下来我们定义了 HelloWorld 这个类,它继承于 Resource 类。这个类中定义一个名为 get 的函数,它返回一个固定的 JSON 为{'hello': 'world'}

最后我们使用 api.add_resource(HelloWorld, '/') 去注册接口,并指定了访问路由,当访问的接口路径为 "/" 且请求方式为 GET 时,就会调用该类中定义好的 get() 函数处理。 你可能已经猜到了,在以 Resource 类为基类的派生类中,就是我们定义不同 HTTP 请求方式的地方,所以在这个类中,你还可以定义 postputdelete 等函数。 接下来,我们在项目根目录中新建一个 run.py 文件:

from app import app
​
​
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

这是一个启动文件,你可以直接在控制台中使用 python run.py 执行,或是和我一样,在项目根目录下新建一个 .env 文件用来存放环境变量:

FLASK_ENV=development # 当前环境
FLASK_DEBUG=True # 开启 debug mode
FLASK_APP=run.py # flask项目入口文件

上面这些环境变量的命名方式都是 Flask 规定的,这样指定环境变量的好处就是我们可以通过控制台执行 flask run 命令来启动服务。 需要注意的是,如果你通过 flask run 命令来启动服务,那么 Flask 的配置会默认以环境变量为准,并且会忽略 run.py 中的配置项。 现在我们启动项目后,看到以下信息就说明服务启动成功了。

  • Serving Flask app 'run.py'
  • Debug mode: on
  • Running on http://127.0.0.1:5000 Press CTRL+C to quit
  • Restarting with stat
  • Debugger is active!
  • Debugger PIN: xxx-xxx-xxx

现在你可以直接使用浏览器访问 http://127.0.0.1:5000/ 或使用 Apifox 等接口调试工具来进行测试,看看是否会得到返回的 {'hello': 'world'} JSON 字符串。

连接数据库

要连接数据库,需要先安装 Flask-SQLAlchemy 、Flask-Migrate 和 pymysql 这三个扩展包,Flask-SQLAlchemy 用来连接并操作数据库,Flask-Migrate 是一个数据库迁移插件,用来同步数据库的更改。最后因为我们要连接的是 MySQL 数据库,所以需要安装一个 pymysql 包。

pip install Flask-SQLAlchemy Flask-Migrate pymysql

接下来我们修改一下我们项目的目录结构,让我们项目的可扩展性更强。

/
├── .venv/
├── app/
│   └── api/ # api 接口模块
│       └── __init__.py # 注册以及生成蓝图
│       └── common/ # 公共方法
│       └── models/ # 模型
│       └── resources/ # 接口
│       └── schema/ # 校验
│   └── __init__.py # 整个应用的初始化
│   └── config.py # 配置项
│   └── manage.py # 数据库迁移工具管理
├── .env # 环境变量
├── run.py # 入口文件

这样修改我们的项目结构,可以让我们配合 Flask 提供的 Blueprint (蓝图) 对接口进行模块化管理和开发,有助于提高我们项目的可扩展性和可维护性。 接下来我们先配置数据库连接,首先你要确保你有可用的 MySQL 数据库,然后在 /app/config.py 中添加如下代码:

import os
​
# 数据库相关配置
# 建议在本地根目录下新建 .env 文件维护敏感信息配置项更安全 
# 用户名
USERNAME = os.getenv('MYSQL_USER_NAME')
# 密码
PASSWORD = os.getenv('MYSQL_USER_PASSWORD')
# 地址
HOSTNAME = os.getenv('MYSQL_HOSTNAME')
# 端口
PORT = os.getenv('MYSQL_PORT')
# 数据库名称
DATABASE = os.getenv('MYSQL_DATABASE_NAME')
​
# 固定格式 不用改
DIALECT = 'mysql'
DRIVER = 'pymysql'
​
class Config(object):
    DEBUG = False
    TESTING = False
    SECRET_KEY = os.getenv('SECRET_KEY')
    SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
    SQLALCHEMY_ECHO = True
​
class ProductionConfig(Config):
    DEBUG = False
    SQLALCHEMY_DATABASE_URI = ''
​
class DevelopmentConfig(Config):
    DEBUG = True
​
class TestingConfig(Config):
    TESTING = True
​
config = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,
    'testing': TestingConfig,
    'default': DevelopmentConfig,
}

然后我们在 .env 文件中新增下面的环境变量:

# ...
SECRET_KEY=b'#q)\\x00\xd6\x9f

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论