Flask-Muck :5分钟内构建 REST API


Flask 生态系统不缺少用于从头开始构建 REST API 的优秀库。缺少的是用于生成常见 CRUD(创建、读取、更新、删除)端点的工具,这些端点通常构成 REST API 的大部分。

Flask-Muck 解决了这个问题,使用 Flask-Muck 你不必担心 CRUD。

  • Flask-Muck 位于 Flask/SQLAlchemy 技术堆栈之上,并使用声明性和模块化方法来替换大量样板代码,只需 9 行代码即可为资源生成一组功能齐全的标准 CRUD 端点。
  • Flask-Muck 与任何生产规模代码库中不可避免的非标准端点共存。
  • Flask-Muck 是一个声明性框架,用于在 Flask、SqlAlchemy、Marshmallow/Pydantic 应用程序堆栈中自动生成带有创建、读取、更新和删除 (CRUD) 端点的 RESTful API,只需 9 行代码。
  •  Flask REST 框架,用于在 SQLAlchemy、Marshmallow/Pydantic 应用程序堆栈中生成 CRUD API 和 OpenAPI 规范。

特点:

  • 使用声明性和模块化方法自动生成 CRUD 端点。
  • 列出资源时内置搜索、过滤、排序和分页。
  • 支持具有嵌套资源的 API(即 /api/classrooms/12345/students)。
  • 与任何其他 Flask 基于方法或基于类的视图完全兼容。与您现有的视图混合搭配。
  • 可在所有操作端点上配置前置和后置回调。允许在创建、更新或删除操作之前和之后添加任意逻辑。
  • 支持 Marshmallow 和 Pydantic 进行模式定义。
  • 动态生成 OpenAPI 规范和 Swagger UI。

项目设置
在开始之前,请确保您具备以下先决条件

  • 安装了 Python 3.9 或更高版本
  • Bash shell 或类似的
  • 对 REST API 的基本了解。

1. 创建项目文件
首先创建所需的文件结构:

mkdir sample_api
cd sample_api
touch app.py

现在,您的项目目录应该有一个 Python 文件:

sample_api/
├─ app.py

重要提示:确保您位于 shell 中的sample_api 目录中。后续教程假设这是所有命令的当前工作目录。

2.安装依赖项
为了从依赖关系开始,我们将使用 Pipenv。如果您更喜欢其他工具来管理环境,请随意使用它。运行以下命令安装 Pipenv:
pip install --user pipenv

接下来,在虚拟环境中安装项目所需的所有依赖项:
pipenv install flask SQLAlchemy flask-sqlalchemy marshmallow flask-muck

您的项目已设置完毕,现在您可以编写一些代码了。

编写代码
在下一节中,您将编写所有 Python 代码来创建 Flask REST API。所有代码片段都应附加到 app.py 文件中。出于演示目的,将根据需要在整个代码中添加模块导入,如果您希望遵守 Pep8 风格指南,请随意将它们分组在文件顶部。

1. 创建一个基本的 Flask 应用程序
在此步骤中,我们设置最基本的 Flask 应用程序。对于此示例,我们保持基本配置,但您可以在许多为生产设置量身定制的记录良好的文章中探索 Flask 应用程序的更全面的配置。

from flask import Flask

app = Flask(__name__)

2.配置SqlAlchemy并添加数据库模型
之前我们安装了依赖项 Flask-SQLAlchemy 和 SQLAlchemy。

  • SQLAlchemy 是一个 SQL 工具包和 ORM,通常与 Flask 结合使用来创建数据库支持的应用程序。我们将使用它来定义我们的数据库表并与它们交互。
  • Flask-SQLAlchemy 是一个扩展,通过设置通用对象和使用这些对象的模式(例如与每个 Web 请求、模型和引擎相关的会话),简化了 SQLAlchemy 与 Flask 的使用。


配置 SQLAlchemy
首先使用 SQLAlchemy 的数据库 URI 更新应用程序的配置。在此示例中,我们将指向本地 sqlite 文件。在生产中,Flask 应配置为使用生产就绪数据库,例如 MySQL 或 PostgreSQL。
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.db"

通过继承DeclarativeBase为所有数据库模型建立一个基类:

from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
    pass
Create a SQLAlchemy extension instance and then initialize the Flask app for use with extension.
from flask_sqlalchemy import SQLAlchemy


db = SQLAlchemy(model_class=Base)
db.init_app(app) 

此时,您现在拥有一个功能齐全的 Flask 应用程序,并且 db 对象已准备好管理应用程序内的数据库交互。

3. 实现数据库模型
现在我们已经配置了应用程序,是时候定义数据库结构了。我们的第一步是创建一个 SQLAlchemy 模型,表示数据库中专用于待办事项的表 - 这是保存应用程序信息的地方。

class TodoModel(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    text = db.Column(db.String, nullable=False)

TodoModel 跟踪数据库中的待办事项。它生成一个包含两列的数据库表:id 和 text。

  • id 是资源的唯一标识符,
  • text 是待办事项的描述。

4. 实施架构
数据模型在定义 API 的请求和响应负载结构方面发挥着至关重要的作用。让我们创建一个 Marshmallow 架构,负责验证请求 JSON 和序列化结果。

import marshmallow as ma
from marshmallow import fields as mf

class TodoSchema(ma.Schema):
    id = mf.Integer(required=True, dump_only=True) 
    text = mf.String(required=True)

记下应用于 id 字段的 dump_only 关键字参数。这意味着该字段专门用于响应中返回的对象的序列化目的。验证请求(加载)时,仅验证文本字段。


5. 创建 Flask-Muck API 视图
Flask 视图中是处理向应用程序发出的 http 请求的代码组件。Flask 提供了一个方便的工具来组织视图代码,在我们深入创建视图之前,让我们通过建立一个蓝图来简化我们的 API 端点来奠定基础。

from flask import Blueprint

api_blueprint = Blueprint("v1_api", __name__, url_prefix="/api/v1/")

添加到此蓝图的所有视图都将附加到 /api/v1 url 路由。

现在,有了组织视图的蓝图,让我们创建它们。在本演示中,我们将利用 Flask-Muck 为我们的待办事项动态生成标准 CRUD 端点。Flask-Muck 提供基于类的视图,可以继承这些视图来生成 CRUD 端点。

from flask_muck import FlaskMuckApiView

class TodoApiView(FlaskMuckApiView):    
    session = db.session
    api_name = "todos"
    Model = TodoModel
    ResponseSchema = TodoSchema
    CreateSchema = TodoSchema
    PatchSchema = TodoSchema
    UpdateSchema = TodoSchema
    searchable_columns = [TodoModel.text]

# Add all url rules to the blueprint.
TodoApiView.add_rules_to_blueprint(api_blueprint)

通过定义一个新的 FlaskMuckApiView 并调用 add_rules_to_blueprint 方法,以下路由被添加到 Flask 应用程序中。

GET /api/todos/列出所有待办事项
POST /api/todos/创建待办事项
GET /api/todos/获取单个待办事项
PUT /api/todos/更新单个待办事项
PATCH /api/todos/修补 a单个待办事项
DELETE /api/todos/删除单个待办事项

6. 定义脚本行为
在最后一步中,我们定义 app.py 作为脚本运行时的行为。
if __name__ == "__main__":
    with app.app_context():
        db.create_all()
    app.run(debug=True)
此代码协调数据库表的创建并启动 Flask 开发服务器。

最终的 app.py 文件应类似于以下内容:

import marshmallow as ma
from flask import Flask, Blueprint
from flask_muck import FlaskMuckApiView
from flask_sqlalchemy import SQLAlchemy
from marshmallow import fields as mf
from sqlalchemy.orm import DeclarativeBase

app = Flask(__name__)


class Base(DeclarativeBase):
    pass


db = SQLAlchemy(model_class=Base)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///todo_example.db"
db.init_app(app)


class TodoModel(db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    text = db.Column(db.String, nullable=False)


class TodoSchema(ma.Schema):
    id = mf.Integer(required=True, dump_only=True)
    text = mf.String(required=True)


api_blueprint = Blueprint(
"v1_api", __name__, url_prefix="/api/v1/")


class TodoApiView(FlaskMuckApiView):
    session = db.session
    api_name =
"todos"
    Model = TodoModel
    ResponseSchema = TodoSchema
    CreateSchema = TodoSchema
    PatchSchema = TodoSchema
    UpdateSchema = TodoSchema
    searchable_columns = [TodoModel.text]


TodoApiView.add_rules_to_blueprint(api_blueprint)
app.register_blueprint(api_blueprint)


if __name__ ==
"__main__":
    with app.app_context():
        db.create_all()
    app.run(debug=True)

启动本地开发服务器
使用以下 shell 命令启动本地开发服务器:
pipenv run python3 app.py
您的服务器现在处于活动状态,地址为http://127.0.0.1:5000。请记住,此配置并未针对生产进行优化。