如何将Flask-RESTful组件应用于构建长尾API?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2368个文字,预计阅读时间需要10分钟。
目录 + Flask-RESTful + 组件 + 一、简介 + 1. 介绍 + 2. REST 特性 + 3. REST 概念 + 4. 环境配置 + 5. 最小API + 二、请求解析 + 1. 请求解析 + 2. 基本参数 + 3. 必需参数 + 4. 多值参数 + 5. 参数转换 + 6. 参数位置
目录- flask-restful 组件
- 一、 简介
- 1、 介绍
- 2、 rest 特性
- 3、 rest 理念
- 4、 环境配置
- 5、 最小的API
- 二、 请求解析
- 1、 基本参数
- 2、 必须参数
- 3、 多值参数
- 4、 参数转移
- 5、 参数位置
- 6、 多个位置
- 7、 继承解析
- 三、 输出字段
- 1、 基本用法
- 2、 重命名属性
- 3、 默认值
- 4、 自定义字段
- 5、 url字段
- 6、 复杂结构
- 7、 列表字段
- 四、 扩展知识
- 1、 响应数据
- 2、 参数验证
- 3、 资源方法装饰器
- 4、 错误处理器
- 五、 服务案例
- 1、 环境
- 2、 模型映射
- 3、 创建路由
- 4、 创建restful服务
- 5、 初始化app
- 一、 简介
Flask-restful 是一个 Flask 扩展,它添加了快速构建 REST APIs 的支持。它当然也是一个能够跟你现有的ORM/库协同工作的轻量级的扩展。Flask-RESTful 鼓励以最小设置的最佳实践。如果你熟悉 Flask 的话,Flask-restful 应该很容易上手。
关于flask的使用,参考我之前的博客:blog.csdn.net/qq_62789540/article/details/124781918
关于flask的组件,参考我之前的文章:blog.csdn.net/qq_62789540/article/details/125563241
flask-restful官方文档:flask-restful.readthedocs.io/en/latest/quickstart.html
flask-restful中文文档:www.pythondoc.com/Flask-RESTful/index.html
2、 rest 特性- Client-Server:服务器端与客户端分离。
- Stateless(无状态):每次客户端请求必需包含完整的信息,换句话说,每一次请求都是独立的。
- Cacheable(可缓存):服务器端必需指定哪些请求是可以缓存的。
- Layered System(分层结构):服务器端与客户端通讯必需标准化,服务器的变更并不会影响客户端。
- Uniform Interface(统一接口):客户端与服务器端的通讯方法必需是统一的。
- Code on demand(按需执行代码?):服务器端可以在上下文中执行代码或者脚本?
REST架构就是为了HTTP协议设计的。RESTful web services的核心概念是管理资源。资源是由URIs来表示,客户端使用HTTP当中的'POST, OPTIONS, GET, PUT, DELETE'等方法发送请求到服务器,改变相应的资源状态。
HTTP请求方法通常也十分合适去描述操作资源的动作:
REST请求并不需要特定的数据格式,通常使用JSON作为请求体,或者URL的查询参数的一部份。
4、 环境配置安装:
pip install flask
pip install flask-restx
5、 最小的API
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "app3.py"
__time__ = "2022/7/8 9:30"
from flask import Flask, url_for
from flask_restx import Resource, Api
app = Flask(__name__)
api = Api(app)
"""
也可以这样
api = Api()
app = Flask(__name__)
api.init_app(app)
"""
# 这里可以使用类装饰器,注册路由,其可以做add_resource能做的事情
# @api.route("/", "/index", endpoint="hello")
class HelloWorld(Resource):
def get(self):
# print(url_for("hello"))
return {
"name": "hello world"
}
def put(self):
pass
def post(self):
pass
def delete(self):
pass
api.add_resource(HelloWorld, '/', "/hello", endpoint="hello") # 添加路由
if __name__ == '__main__':
app.run("0.0.0.0", 5000, debug=True)
二、 请求解析
Flask-RESTful的请求解析接口是模仿argparse接口。它设计成提供简单并且同一的访问Flask中flask.request 对象里的任何变量的入口
from flask_restful import reqparse
parser = reqparse.RequestParser() # 创建一个参数接收器
parser.add_argument('rate', type=int, help='Rate cannot be converted') # 添加基本参数
parser.add_argument('name', type=str)
args = parser.parse_args() # 解析参数
2、 必须参数如果你指定了 help 参数的值,在解析的时候当类型错误被触发的时候,它将会被作为错误信息给呈现出来。如果你没有指定 help 信息的话,默认行为是返回类型错误本身的信息。
默认下,arguments 不是 必须的。另外,在请求中提供的参数不属于 RequestParser 的一部分的话将会被忽略。
另请注意:在请求解析中声明的参数如果没有在请求本身设置的话将默认为
None。
要求一个值传递的参数,只需要添加required=True来调用add_argument()
parser.add_argument('name', type=str, required=True,
help="Name cannot be blank!")
3、 多值参数
如果你要接受一个键有多个值的话,你可以传入 action='append'
parser.add_argument('name', type=str, action='append')
这样,查询的话:
curl api.example.com -d "Name=bob" -d "Name=sue" -d "Name=joe"
4、 参数转移
如果由于某些原因,你想要以不同的名称存储你的参数,一旦它被解析的时候,你可以使用dest=arg
parser.add_argument('name', type=str, dest='public_name')
args = parser.parse_args()
print(args['public_name'])
5、 参数位置
默认下,RequestParser 试着从 flask.Request.values,以及 flask.Request.json 解析值。
在 add_argument() 中使用 location 参数可以指定解析参数的位置。flask.Request 中任何变量都能被使用。例如:
# Look only in the POST body
parser.add_argument('name', type=int, location='form')
# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')
# From the request headers
parser.add_argument('User-Agent', type=str, location='headers')
# From /app.db"
SQLALCHEMY_DATABASE_URI = DB_URI # 使用sqlachemy
SQLALCHEMY_TRACK_MODIFICATIONS = True
SWAGGER_TITLE = "API"
SWAGGER_DESC = "API接口"
# 地址,必须带上端口号
SWAGGER_HOST = "localhost:5000"
class Product():
pass
2、 模型映射
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "models.py"
__time__ = "2022/7/9 21:32"
from . import db
class Foo(db.Model):
"""
模型,将映射到数据库表中
"""
def __init__(self, id, name, age):
self.id = id
self.name = name
self.age = age
__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)
然后在终端运行:
flask db init
flask db migrate
flask db upgrade
3、 创建路由
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "test.py"
__time__ = "2022/7/9 21:23"
from flask import Blueprint, url_for, redirect
from flaskApp.models import Foo
from flaskApp import db
te = Blueprint("te", __name__)
from . import api_te
@te.route("/index")
def index():
"""则,这里只要关注返回页面的请求,返回数据交给restful去处理"""
return redirect(url_for("te.operateData")) # 这里就只是进行一个简单的模拟,进行重定向访问,实际开发中可以使用Ajax异步请求
@te.route("/add")
def search():
"""这里为了方便,我们使用add路由来添加数据"""
db.session.add(Foo(1, "李华", 23))
db.session.commit()
db.session.remove()
return "success"
4、 创建restful服务
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "api_te.py"
__time__ = "2022/7/9 21:52"
from flask import request, jsonify
from .test import te
from flask_restful import Api, Resource, fields, marshal_with, reqparse
from flaskApp import db
from flaskApp.models import Foo
from flaskApp.tools import HttpCode
api = Api(te)
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)
class FooListApi(Resource):
# 定义要返回的字段
resource_fields = {
'id': fields.Integer,
'name': fields.String,
'age': fields.String
}
# 装饰器,定义返回数据
@marshal_with(resource_fields)
def get(self):
"""
返回所有记录
:return:
"""
parser = reqparse.RequestParser()
parser.add_argument('name', type=str, location='args', help='必须输入姓名') # 注意,如果添加了parser参数解析,则,返回数据需要是JSON数据
arg = parser.parse_args()
print(arg)
# 127.0.0.1:5000/api/v1/foo?name=1&a=2 终端输出: {'name': '1'}
# 查询数据库
foos = db.session.query(Foo).all()
return {
"data": foos,
"status": HttpCode.ok
}
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("新增一条记录成功!")
# 所有记录
api.add_resource(FooListApi, '/api/v1/foo', endpoint="operateData") # 返回数据
5、 初始化app
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "__init__.py"
__time__ = "2022/7/9 21:20"
from flask import Flask
from . import settings
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from .views.test import te # 必须要在db创建后导入
def create_app():
app = Flask(__name__)
app.register_blueprint(te)
app.config.from_object(settings.Basic)
db.init_app(app)
return app
完整项目在:github.com/liuzhongkun1/flask_/tree/main/flaskRestful
本文共计2368个文字,预计阅读时间需要10分钟。
目录 + Flask-RESTful + 组件 + 一、简介 + 1. 介绍 + 2. REST 特性 + 3. REST 概念 + 4. 环境配置 + 5. 最小API + 二、请求解析 + 1. 请求解析 + 2. 基本参数 + 3. 必需参数 + 4. 多值参数 + 5. 参数转换 + 6. 参数位置
目录- flask-restful 组件
- 一、 简介
- 1、 介绍
- 2、 rest 特性
- 3、 rest 理念
- 4、 环境配置
- 5、 最小的API
- 二、 请求解析
- 1、 基本参数
- 2、 必须参数
- 3、 多值参数
- 4、 参数转移
- 5、 参数位置
- 6、 多个位置
- 7、 继承解析
- 三、 输出字段
- 1、 基本用法
- 2、 重命名属性
- 3、 默认值
- 4、 自定义字段
- 5、 url字段
- 6、 复杂结构
- 7、 列表字段
- 四、 扩展知识
- 1、 响应数据
- 2、 参数验证
- 3、 资源方法装饰器
- 4、 错误处理器
- 五、 服务案例
- 1、 环境
- 2、 模型映射
- 3、 创建路由
- 4、 创建restful服务
- 5、 初始化app
- 一、 简介
Flask-restful 是一个 Flask 扩展,它添加了快速构建 REST APIs 的支持。它当然也是一个能够跟你现有的ORM/库协同工作的轻量级的扩展。Flask-RESTful 鼓励以最小设置的最佳实践。如果你熟悉 Flask 的话,Flask-restful 应该很容易上手。
关于flask的使用,参考我之前的博客:blog.csdn.net/qq_62789540/article/details/124781918
关于flask的组件,参考我之前的文章:blog.csdn.net/qq_62789540/article/details/125563241
flask-restful官方文档:flask-restful.readthedocs.io/en/latest/quickstart.html
flask-restful中文文档:www.pythondoc.com/Flask-RESTful/index.html
2、 rest 特性- Client-Server:服务器端与客户端分离。
- Stateless(无状态):每次客户端请求必需包含完整的信息,换句话说,每一次请求都是独立的。
- Cacheable(可缓存):服务器端必需指定哪些请求是可以缓存的。
- Layered System(分层结构):服务器端与客户端通讯必需标准化,服务器的变更并不会影响客户端。
- Uniform Interface(统一接口):客户端与服务器端的通讯方法必需是统一的。
- Code on demand(按需执行代码?):服务器端可以在上下文中执行代码或者脚本?
REST架构就是为了HTTP协议设计的。RESTful web services的核心概念是管理资源。资源是由URIs来表示,客户端使用HTTP当中的'POST, OPTIONS, GET, PUT, DELETE'等方法发送请求到服务器,改变相应的资源状态。
HTTP请求方法通常也十分合适去描述操作资源的动作:
REST请求并不需要特定的数据格式,通常使用JSON作为请求体,或者URL的查询参数的一部份。
4、 环境配置安装:
pip install flask
pip install flask-restx
5、 最小的API
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "app3.py"
__time__ = "2022/7/8 9:30"
from flask import Flask, url_for
from flask_restx import Resource, Api
app = Flask(__name__)
api = Api(app)
"""
也可以这样
api = Api()
app = Flask(__name__)
api.init_app(app)
"""
# 这里可以使用类装饰器,注册路由,其可以做add_resource能做的事情
# @api.route("/", "/index", endpoint="hello")
class HelloWorld(Resource):
def get(self):
# print(url_for("hello"))
return {
"name": "hello world"
}
def put(self):
pass
def post(self):
pass
def delete(self):
pass
api.add_resource(HelloWorld, '/', "/hello", endpoint="hello") # 添加路由
if __name__ == '__main__':
app.run("0.0.0.0", 5000, debug=True)
二、 请求解析
Flask-RESTful的请求解析接口是模仿argparse接口。它设计成提供简单并且同一的访问Flask中flask.request 对象里的任何变量的入口
from flask_restful import reqparse
parser = reqparse.RequestParser() # 创建一个参数接收器
parser.add_argument('rate', type=int, help='Rate cannot be converted') # 添加基本参数
parser.add_argument('name', type=str)
args = parser.parse_args() # 解析参数
2、 必须参数如果你指定了 help 参数的值,在解析的时候当类型错误被触发的时候,它将会被作为错误信息给呈现出来。如果你没有指定 help 信息的话,默认行为是返回类型错误本身的信息。
默认下,arguments 不是 必须的。另外,在请求中提供的参数不属于 RequestParser 的一部分的话将会被忽略。
另请注意:在请求解析中声明的参数如果没有在请求本身设置的话将默认为
None。
要求一个值传递的参数,只需要添加required=True来调用add_argument()
parser.add_argument('name', type=str, required=True,
help="Name cannot be blank!")
3、 多值参数
如果你要接受一个键有多个值的话,你可以传入 action='append'
parser.add_argument('name', type=str, action='append')
这样,查询的话:
curl api.example.com -d "Name=bob" -d "Name=sue" -d "Name=joe"
4、 参数转移
如果由于某些原因,你想要以不同的名称存储你的参数,一旦它被解析的时候,你可以使用dest=arg
parser.add_argument('name', type=str, dest='public_name')
args = parser.parse_args()
print(args['public_name'])
5、 参数位置
默认下,RequestParser 试着从 flask.Request.values,以及 flask.Request.json 解析值。
在 add_argument() 中使用 location 参数可以指定解析参数的位置。flask.Request 中任何变量都能被使用。例如:
# Look only in the POST body
parser.add_argument('name', type=int, location='form')
# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')
# From the request headers
parser.add_argument('User-Agent', type=str, location='headers')
# From /app.db"
SQLALCHEMY_DATABASE_URI = DB_URI # 使用sqlachemy
SQLALCHEMY_TRACK_MODIFICATIONS = True
SWAGGER_TITLE = "API"
SWAGGER_DESC = "API接口"
# 地址,必须带上端口号
SWAGGER_HOST = "localhost:5000"
class Product():
pass
2、 模型映射
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "models.py"
__time__ = "2022/7/9 21:32"
from . import db
class Foo(db.Model):
"""
模型,将映射到数据库表中
"""
def __init__(self, id, name, age):
self.id = id
self.name = name
self.age = age
__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)
然后在终端运行:
flask db init
flask db migrate
flask db upgrade
3、 创建路由
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "test.py"
__time__ = "2022/7/9 21:23"
from flask import Blueprint, url_for, redirect
from flaskApp.models import Foo
from flaskApp import db
te = Blueprint("te", __name__)
from . import api_te
@te.route("/index")
def index():
"""则,这里只要关注返回页面的请求,返回数据交给restful去处理"""
return redirect(url_for("te.operateData")) # 这里就只是进行一个简单的模拟,进行重定向访问,实际开发中可以使用Ajax异步请求
@te.route("/add")
def search():
"""这里为了方便,我们使用add路由来添加数据"""
db.session.add(Foo(1, "李华", 23))
db.session.commit()
db.session.remove()
return "success"
4、 创建restful服务
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "api_te.py"
__time__ = "2022/7/9 21:52"
from flask import request, jsonify
from .test import te
from flask_restful import Api, Resource, fields, marshal_with, reqparse
from flaskApp import db
from flaskApp.models import Foo
from flaskApp.tools import HttpCode
api = Api(te)
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)
class FooListApi(Resource):
# 定义要返回的字段
resource_fields = {
'id': fields.Integer,
'name': fields.String,
'age': fields.String
}
# 装饰器,定义返回数据
@marshal_with(resource_fields)
def get(self):
"""
返回所有记录
:return:
"""
parser = reqparse.RequestParser()
parser.add_argument('name', type=str, location='args', help='必须输入姓名') # 注意,如果添加了parser参数解析,则,返回数据需要是JSON数据
arg = parser.parse_args()
print(arg)
# 127.0.0.1:5000/api/v1/foo?name=1&a=2 终端输出: {'name': '1'}
# 查询数据库
foos = db.session.query(Foo).all()
return {
"data": foos,
"status": HttpCode.ok
}
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("新增一条记录成功!")
# 所有记录
api.add_resource(FooListApi, '/api/v1/foo', endpoint="operateData") # 返回数据
5、 初始化app
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "__init__.py"
__time__ = "2022/7/9 21:20"
from flask import Flask
from . import settings
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from .views.test import te # 必须要在db创建后导入
def create_app():
app = Flask(__name__)
app.register_blueprint(te)
app.config.from_object(settings.Basic)
db.init_app(app)
return app
完整项目在:github.com/liuzhongkun1/flask_/tree/main/flaskRestful

