上一篇文章,介绍了使用 Java + Spring Boot + MyBatis 构建 RESTful API 的详细步骤;很多小伙伴表示,更愿意用 Python 编写 RESTful API 服务,希望我能写一下
本篇将以?Python?开始介绍搭建?RESTful API 的流程?,使用的技术栈是:Flask?+ flask-restful + flasgger
使用 Python 编写 RESTful 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
首先,我们使用 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?去测试接口了
在实际项目开发中,数据结构、层级关系往往要复杂很多,我们需要对项目进行一次整合,按功能进行封装,具体步骤如下:
第 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/#/
上面就是通过 Flask + flask_restful 单表实现 RESTful API 完整的流程了,项目中涉及的多表,只需要更改数据库的逻辑操作就可以了
我已经将文中全部源码上传到公众号后台,关注公众号后回复「?rest2?」即可获得全部源码
如果你觉得文章还不错,请大家点赞分享下。你的肯定是我最大的鼓励和支持。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。