教你 10 分钟构建一套 RESTful API 服务( 中 )

    技术2022-08-31  73

    Python实战社群

    Java实战社群

    长按识别下方二维码,按需求添加

    扫码关注添加客服

    进Python社群▲

    扫码关注添加客服

    进Java社群▲

    作者丨星安果 

    来源丨AirPython(AirPython)

    1. 前言

    上一篇文章,介绍了使用 Java + Spring Boot + MyBatis 构建 RESTful API 的详细步骤;很多小伙伴表示,更愿意用 Python 编写 RESTful API 服务,希望我能写一下

    本篇将以 Python 开始介绍搭建 RESTful API 的流程 ,使用的技术栈是:Flask + flask-restful + flasgger

    2. 安装依赖

    使用 Python 编写 RESTful API 之前,我们需要先在虚拟环境内安装对应的依赖

    具体包含:

    Flask- 基础 Web 框架

    flask_restful- Flask 的扩展,增加了对快速构建 REST API 的支持

    flasgger- flask 支持的 Swagger UI,可以生成 API 接口文档

    # 安装flask pip3 install flask # 安装flask-restful pip3 install flask-restful # 安装flasgger # 注意:需要更新setuptools pip3 install -U setuptools pip3 install flasgger # 管理数据库的依赖 pip3 install flask_script pip3 install flask_migrate

    3. Hello World

    首先,我们使用 Pycharm 创建一个 Flask Web 项目,初始化代码如下:

    from flask import Flask app = Flask(__name__) @app.route('/') def hello_world():     return 'Hello World!' if __name__ == '__main__':     app.run()

    从 flask_restful 文件中导入 Api、Resource 两个类,使用上面的 app 对象,构建一个 api 对象,接着准备一个列表数据

    from flask_restful import Api,Resource app = Flask(__name__) # 实例化一个 Api 对象,用来创建、管理 RESTful Api api = Api(app) # 准备一个列表数据 datas = [{'id': 1, 'name': 'xag', 'age': 18}, {'id': 2, 'name': 'xingag', 'age': 19}]

    然后,利用 Flask 中的 CBV 模式,创建一个 Resource 类的子类,用于定义资源路由

    这里以 GET / POST 动作为例,重写 get、post 方法,并编写内部逻辑,返回数据即可

    class UserView(Resource):     """     通过继承 Resource 来实现调用 GET/POST 等动作方法     """     def get(self):         """         GET 请求         :return:         """         return {'code': 200, 'msg': 'success', 'data': datas}     def post(self):         # 参数数据         json_data = request.get_json()         # 追加数据到列表中         new_id = len(datas)+1         datas.append({'id':new_id,**json_data})         # 返回新增的最后一条数据         return {'code': 200, 'msg': 'ok', 'success': datas[new_id - 1]}

    最后,使用 Api 的实例对象,将上面定义的资源,利用路径,完全暴露出去

    # 暴露接口出去 # 资源路由:UserView # 路径:/user api.add_resource(UserView,'/user')

    运行程序后,就可以拿 Postman 或 cURL 去测试接口了

    4. 项目实战

    在实际项目开发中,数据结构、层级关系往往要复杂很多,我们需要对项目进行一次整合,按功能进行封装,具体步骤如下:

    第 1 步,编写配置文件

    新建一个配置文件 config.py,将数据库( 以 Mysql 为例 )的连接信息,包含:用户名、密码、端口号、数据库名、连接驱动和 Swagger 的设置信息追加进去

    # config.py USERNAME = 'root' PASSWORD = 'root' HOSTNAME = "127.0.0.1" PORT = '3306' DATABASE = 'xag' DIALECT = 'mysql' DRIVER = 'pymysql' # 连接数据的URI DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE) SQLALCHEMY_DATABASE_URI = DB_URI SQLALCHEMY_TRACK_MODIFICATIONS = True SWAGGER_TITLE = "API" SWAGGER_DESC = "API接口" # 地址,必须带上端口号 SWAGGER_HOST = "localhost:5000"

    第 2 步,模型映射数据库

    创建一个模型类 Foo 继承 SQLAlchemy 对象,使用  __tablename__ 指定生成数据表的名称、然后新增几个常用字段

    # models.py from exts import db class Foo(db.Model):     """     模型,将映射到数据库表中     """     __tablename__ = 'foo'     # 主键ID     id = db.Column(db.INTEGER, primary_key=True, autoincrement=True)     # 名字     name = db.Column(db.String(100), nullable=False)     # 年龄     age = db.Column(db.INTEGER)

    接着,创建 manage.py 文件

    显式导入上面创建的 Foo 类,使用 flask_migrate 中的 Migrate 绑定 App 和数据库,利用 flask_script 中的 Manager 实例去添加一个脚本命令

    # manager.py from flask_migrate import Migrate, MigrateCommand from flask_script import Manager from exts import db from api_app import app from models import Foo manager = Manager(app) migrate=Migrate(app, db) manager.add_command('db', MigrateCommand) if __name__ == '__main__':     manager.run()

    需要注意的是,Foo 模型必须显式导入,否则没法映射到数据库中

    最后,通过下面 3 个脚本命令,将模型映射到数据库中

    除了第一次需要生成迁移脚本外,后面映射数据库,只需要执行后面两个命令即可

    # 初始化迁移文件 python3 manager.py db init # 映射到文件 python3 manager.py db migrate # 映射到数据库 python3 manager.py db upgrade

    打开 Navicat For Mysql,即可以看到刚刚映射过来的数据表及迁移表

    第 3 步,创建资源路由

    下面以创建列表查询( GET )、单条记录的查询( GET )、更新( PUT )、新增( POST )、删除( DELETE )为例

    flask_restful 中的 marshal_with 类可以作为装饰器,定义到动作函数上,指定要返回的字段;然后使用 SQLAlchemy ORM 操作数据库,将数据直接进行返回

    比如:返回获取数据列表

    # api_foo.py from flask_restful import Resource, fields, marshal_with, request class FooListApi(Resource):     # 定义要返回的字段     resource_fields = {         'id': fields.Integer,         'name': fields.String,         'age': fields.String     }     # 装饰器,定义返回数据     @marshal_with(resource_fields)     def get(self):         """         返回所有记录         :return:         """         # 查询数据库         foos = db.session.query(Foo).all()         return foos

    对于新增一个对象( POST 动作)

    # api_foo.py class FooApi(Resource):     def post(self):         """         创建一条记录         :return:         """         # 参数         params = request.get_json()         name = params.get("name")         age = params.get("age")         # 构建一个模型         foo = Foo(name=name, age=age)         # 加入到数据库         db.session.add(foo)         db.session.commit()         return success("新增一条记录成功!")

    第 4 步,返回数据统一化

    为了保证返回的数据结构一致,可以将返回码、返回信息及数据进行一次封装,通过jsonify进行格式化返回

    # restful_utils.py from flask import jsonify class HttpCode(object):     ok = 200     un_auth_error = 401     params_error = 400     server_error = 500 def restful_result(code, message, data):     return jsonify({"code": code, "message": message, "data": data or {}}) def success(message="", data=None):     """     正确返回     :return:     """     return restful_result(code=HttpCode.ok, message=message, data=data)

    第 5 步,暴露接口

    使用 flask_restful 中的 Api 实例对象,将上面定义的资源路由暴露出去

    #api_app.py from flask_restful import Api api = Api(app) # 某一条记录 api.add_resource(FooApi, '/api/v1/foo','/api/v1/foo/<int:id>') # 所有记录 api.add_resource(FooListApi, '/api/v1/foos')

    第 6 步,自动生成接口文档

    Flask 中同样可以利用 Swagger 自动生成接口帮助文档

    首先,从配置文件 config.py 中读取配置,实例化 Swagger 对象

    #api_app.py from flasgger import Swagger # API可视化管理 swagger_config = Swagger.DEFAULT_CONFIG # 标题 swagger_config['title'] = config.SWAGGER_TITLE    # 描述信息 swagger_config['description'] = config.SWAGGER_DESC # Host     swagger_config['host'] = config.SWAGGER_HOST     # 实例化 swagger = Swagger(app,config=swagger_config)

    然后,在资源路由的动作内新增 swagger 注释内容,包含:请求方式、参数、响应数据、描述信息等

    具体可以参考:http://editor.swagger.io/#/

    以获取某一条数据为例:

    class FooApi(Resource):     resource_fields = {         'id': fields.Integer,         'name': fields.String,         'age': fields.String     }     @marshal_with(resource_fields)     def get(self, id):         """获取用户信息     ---     schemes:       - http     parameters:       - name: id         in: path         type: integer         required: true         default: 1         description: 用户id     responses:       200:         description: 返回用户信息         examples:                 {                     "id": 1,                     "name": "xag",                     "age":"18"                 }     """         foo = db.session.query(Foo).get(id)         return foo

    最后,运行项目,访问下面的链接,即可以看到定义好的 RESTful API 服务了

    http://localhost:5000/apidocs/#/

    5. 最后

    上面就是通过 Flask + flask_restful 单表实现 RESTful API 完整的流程了,项目中涉及的多表,只需要更改数据库的逻辑操作就可以了

    程序员专栏 扫码关注填加客服 长按识别下方二维码进群 近期精彩内容推荐:   再见!蚂蚁金服 微信支付的架构到底有多牛? API 接口四连问!就问你,怕不怕! Python这么慢,为啥大公司还在用? 在看点这里好文分享给更多人↓↓
    Processed: 0.011, SQL: 9