前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >教你 10 分钟构建一套 RESTful API 服务( 中 )

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

原创
作者头像
AirPython
修改2020-06-16 10:09:07
1.6K2
修改2020-06-16 10:09:07
举报
文章被收录于专栏:Python 自动化Python 自动化

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 接口文档
代码语言:javascript
复制
#?安装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?项目,初始化代码如下:

代码语言:javascript
复制
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 对象,接着准备一个列表数据

代码语言:javascript
复制
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 方法,并编写内部逻辑,返回数据即可

代码语言:javascript
复制
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 的实例对象,将上面定义的资源,利用路径,完全暴露出去

代码语言:javascript
复制
#?暴露接口出去
#?资源路由:UserView
#?路径:/user
api.add_resource(UserView,'/user')

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

4. 项目实战

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

第 1 步,编写配置文件

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

代码语言:javascript
复制
#?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__ 指定生成数据表的名称、然后新增几个常用字段

代码语言:javascript
复制
#?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 实例去添加一个脚本命令

代码语言:javascript
复制
#?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 个脚本命令,将模型映射到数据库中

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

代码语言:javascript
复制
?#?初始化迁移文件
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 操作数据库,将数据直接进行返回

比如:返回获取数据列表

代码语言:javascript
复制
#?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 动作)

代码语言:javascript
复制
#?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进行格式化返回

代码语言:javascript
复制
#?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 实例对象,将上面定义的资源路由暴露出去

代码语言:javascript
复制
#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 对象

代码语言:javascript
复制
#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/#/

以获取某一条数据为例:

代码语言:javascript
复制
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 完整的流程了,项目中涉及的多表,只需要更改数据库的逻辑操作就可以了

我已经将文中全部源码上传到公众号后台,关注公众号后回复「?rest2?」即可获得全部源码

如果你觉得文章还不错,请大家点赞分享下。你的肯定是我最大的鼓励和支持。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.?前言
  • 2. 安装依赖
  • 3. Hello World
  • 4. 项目实战
  • 5. 最后
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com