Flask-RESTful 分析

一只猴子在接线,背景是集成电路,整个场景采用了幽默卡通风格,色彩鲜艳

Flask-RESTful 是一个 Flask 扩展,它为构建 RESTful API 提供了方便的工具和资源。它简化了创建 RESTful 服务的过程,允许开发者专注于业务逻辑而不是 HTTP 协议的细节。

  1. 资源(Resources)
    • Resource 类:是 Flask-RESTful 的核心,它代表一个 RESTful 资源。开发者可以通过继承 Resource 类并定义 HTTP 方法(如 get, post, put, delete 等)来创建资源。
    • 方法装饰器:可以使用 @marshal_with 装饰器来序列化输出数据,使用 @expect 装饰器来声明期望的输入数据。
  2. 字段(Fields)和_marshall_with
    • 字段:是 Flask-RESTful 中的一个重要概念,用于定义如何将 Python 对象转换为 JSON。Field 类及其子类(如 StringField, IntegerField 等)用于描述和格式化输出。
    • marshal_with:是一个装饰器,用于指定一个字段列表(称为_marshallSchema),它定义了如何将资源方法返回的数据转换为 JSON。
  3. 请求解析(Request Parsing)
    • Flask-RESTful 提供了请求解析功能,允许开发者定义输入数据的格式和类型。使用 reqparse.RequestParser 类,可以添加参数并指定参数类型、默认值、位置(如 JSON, 表单等)和其他验证器。
  4. API
    • Api 类:是 Flask-RESTful 应用的入口点。它管理资源与 URL 的映射,并处理请求的分发。使用 Api 实例的 add_resource 方法可以将资源添加到应用中。
  5. 异常处理(Error Handling)
    • Flask-RESTful 允许开发者定义自定义异常和错误处理逻辑。可以通过继承 restful.Api 类并重写 handle_error 方法来实现自定义错误处理。
  6. 认证(Authentication)
    • Flask-RESTful 可以与 Flask 的认证扩展(如 Flask-Login)一起使用,以保护 API 并验证用户身份。
  7. API 版本控制
    • Flask-RESTful 支持通过蓝图和子域来实现 API 的版本控制。
  8. 完整性和性能
    • Flask-RESTful 提供了数据完整性的保证,确保客户端接收到的数据是完整和一致的。同时,它也考虑了性能优化,如使用缓存来提高响应速度。
      Flask-RESTful 的目标是提供一个简单的框架,让开发者能够以最少的工作量创建出符合 REST 架构风格的 Web 服务。通过利用 Flask 的简洁性和 Flask-RESTful 的强大功能,开发者可以快速构建出高效、可靠的 API。

最小API

# 导入 Flask 和 Flask-RESTful 的相关类
from flask import Flask
from flask_restful import Resource, Api
# 创建 Flask 应用实例
app = Flask(__name__)
# 创建 Flask-RESTful API 实例
api = Api(app)
# 定义一个名为 HelloWorld 的资源类,继承自 flask_restful.Resource
class HelloWorld(Resource):
    # 定义 GET 方法,当客户端发送 GET 请求时会调用这个方法
    def get(self):
        # 返回一个字典,其中包含一个键值对 'hello': 'world'
        return {'hello': 'world'}
# 将 HelloWorld 资源添加到 API 路由中,设置其 URL 为 '/'
api.add_resource(HelloWorld, '/')
# 当此脚本作为主程序运行时(而不是被导入时),执行以下代码
if __name__ == '__main__':
    # 启动 Flask 应用,开启 debug 模式以提供调试信息
    app.run(debug=True)

这段代码创建了一个基本的 Flask 应用,并使用 Flask-RESTful 扩展添加了一个简单的 RESTful API。当你在浏览器或使用工具(如 curl)访问服务器的根 URL(http://localhost:5000/)时,你会得到一个 JSON 响应 {"hello": "world"}

与资源交互

这段代码创建了一个简单的待办事项(Todo)管理应用,允许用户通过HTTP GET和PUT请求来检索和更新待办事项。

# 导入Flask和Flask-RESTful的相关类
from flask import Flask, request
from flask_restful import Resource, Api
# 创建Flask应用实例
app = Flask(__name__)
# 创建Flask-RESTful API实例
api = Api(app)
# 创建一个字典来存储待办事项,键为todo_id,值为待办事项的内容
todos = {}
# 定义一个名为TodoSimple的资源类,继承自flask_restful.Resource
class TodoSimple(Resource):
    # 定义GET方法,当客户端发送GET请求时会调用这个方法
    #(todo_id)表示这个方法是带参数的,参数名为todo_id
    def get(self, todo_id):
        # 从todos字典中获取todo_id对应的待办事项,并返回
        # 如果todo_id不存在,会抛出一个KeyError异常
        return {todo_id: todos[todo_id]}
    # 定义PUT方法,当客户端发送PUT请求时会调用这个方法
    #(todo_id)表示这个方法是带参数的,参数名为todo_id
    def put(self, todo_id):
        # 从请求的表单数据中获取'data'字段,并将其存储在todos字典中
        # todo_id作为键,request.form['data']作为值
        todos[todo_id] = request.form['data']
        # 返回更新后的待办事项
        return {todo_id: todos[todo_id]}
# 将TodoSimple资源添加到API路由中,设置其URL为'/<string:todo_id>'
# 这里的<string:todo_id>表示todo_id是一个字符串类型的参数
api.add_resource(TodoSimple, '/<string:todo_id>')
# 当此脚本作为主程序运行时(而不是被导入时),执行以下代码
if __name__ == '__main__':
    # 启动Flask应用,开启debug模式以提供调试信息
    app.run(debug=True)

这段代码定义了一个名为 TodoSimple 的资源,它有两个方法:getputget 方法用于检索指定 todo_id 的待办事项,而 put 方法用于创建或更新待办事项的内容。待办事项的数据存储在全局字典 todos 中。应用运行后,可以通过发送 HTTP 请求到 /todo_id 来与资源进行交互。

定义响应头

这段代码定义了三个Flask-RESTful资源类,每个类都只有一个GET方法,但它们在返回响应时有所不同。

# 导入Flask-RESTful的Resource类
from flask_restful import Resource
# 定义一个名为Todo1的资源类,继承自flask_restful.Resource
class Todo1(Resource):
    # 定义GET方法,当客户端发送GET请求时会调用这个方法
    def get(self):
        # 返回一个字典{'task': 'Hello world'},HTTP响应码默认为200 OK
        return {'task': 'Hello world'}
# 定义一个名为Todo2的资源类,继承自flask_restful.Resource
class Todo2(Resource):
    # 定义GET方法,当客户端发送GET请求时会调用这个方法
    def get(self):
        # 返回一个字典{'task': 'Hello world'},HTTP响应码设置为201 Created
        return {'task': 'Hello world'}, 201
# 定义一个名为Todo3的资源类,继承自flask_restful.Resource
class Todo3(Resource):
    # 定义GET方法,当客户端发送GET请求时会调用这个方法
    def get(self):
        # 返回一个字典{'task': 'Hello world'},HTTP响应码设置为201 Created
        # 并添加自定义响应头{'Etag': 'some-opaque-string'}
        return {'task': 'Hello world'}, 201, {'Etag': 'some-opaque-string'}

在这个例子中,每个类都代表一个可以访问的资源。Todo1 返回一个默认的200响应码,表示请求成功。Todo2 返回一个201响应码,通常用于创建资源的响应,表示请求已成功处理并创建了新的资源。Todo3 也返回一个201响应码,但同时还包括了一个自定义的响应头Etag,这通常用于缓存验证,表示资源的版本信息。
这些类可以添加到Flask-RESTful的API中,并通过相应的URL路径进行访问。每个类的get方法都可以通过HTTP GET请求来调用,返回一个 JSON 响应 {"hello": "world"}

参数验证

这段代码使用了 Flask-RESTful 的 reqparse 模块来解析请求参数。

# 导入 Flask-RESTful 的 reqparse 模块
from flask_restful import reqparse
# 创建一个 RequestParser 实例,用于解析请求中的参数
parser = reqparse.RequestParser()
# 使用 add_argument 方法添加一个参数 'rate' 到解析器中
# 参数类型设置为 int,表示期望 'rate' 是一个整数
# help='Rate to charge for this resource' 提供了一个帮助信息,当参数验证失败时会显示这个信息
parser.add_argument('rate', type=int, help='Rate to charge for this resource')
# 调用 parse_args 方法来解析请求中的参数
# 如果请求中包含 'rate' 参数,它会将其转换为整数,并存储在 args 对象中
# 如果 'rate' 参数不存在或者不是整数,Flask-RESTful 会返回一个 400 Bad Request 响应,并显示帮助信息
args = parser.parse_args()
# 现在 args 对象包含了请求中的 'rate' 参数,可以直接使用 args['rate'] 来获取其值
# 调用 parse_args 方法来解析请求中的参数
# strict=True 参数指定了严格模式,只有预先在解析器中定义的参数会被接受
# 如果请求中包含未定义的参数,将抛出一个 BadRequest 异常,导致 400 Bad Request 响应
args = parser.parse_args(strict=True)

在这个例子中,parser 对象被用来定义期望从请求中解析出的参数。add_argument 方法用于指定参数的名称、类型和帮助信息。当 parse_args 方法被调用时,它会解析实际的请求,提取出 rate 参数,并将其转换为整数类型。如果解析过程中出现问题(例如,rate 参数不是整数),Flask-RESTful 会自动生成一个错误响应。

格式化数据

这段代码展示了如何使用 Flask-RESTful 的 marshal_with 装饰器和 fields 模块来格式化资源类的输出。

# 导入 Flask-RESTful 的 fields 和 marshal_with
from flask_restful import fields, marshal_with
# 定义一个字段映射,指定了资源返回的数据结构
# 'task' 字段将被格式化为字符串,'uri' 字段将被格式化为 URL
# 'uri' 字段的值 'todo_ep' 是一个 endpoint 名称,用于生成 URL
resource_fields = {
    'task':   fields.String,
    'uri':    fields.Url('todo_ep')
}
# 定义一个 TodoDao 类,代表待办事项的数据访问对象
class TodoDao(object):
    def __init__(self, todo_id, task):
        self.todo_id = todo_id
        self.task = task
        # 定义一个 'status' 属性,但注释指出这个字段不会包含在响应中
        self.status = 'active'
# 定义一个 Todo 资源类,继承自 flask_restful.Resource
class Todo(Resource):
    # 使用 marshal_with 装饰器,指定了返回值应该使用 resource_fields 来格式化
    @marshal_with(resource_fields)
    def get(self, **kwargs):
        # 创建一个 TodoDao 实例,并传入 todo_id 和 task
        return TodoDao(todo_id='my_todo', task='Remember the milk')

在这个例子中,marshal_with 装饰器用于指定返回值的格式。resource_fields 字典定义了哪些字段应该包含在响应中,以及它们应该如何被格式化。fields.String 表示该字段应该被格式化为字符串,而 fields.Url 表示该字段应该被格式化为 URL,todo_ep 是一个 endpoint 名称,它将被用于生成实际的 URL。
TodoDao 类是一个简单的数据访问对象,它包含了 todo_idtaskstatus 属性。在 Todo 资源类的 get 方法中,创建了一个 TodoDao 实例,并返回它。由于 marshal_with 装饰器的使用,只有 taskuri 字段会被包含在最终的响应中,而 status 字段会被忽略。

完整示例

# 导入 Flask 和 Flask-RESTful 的相关类
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
# 创建 Flask 应用实例
app = Flask(__name__)
# 创建 Flask-RESTful API 实例
api = Api(app)
# 定义一个字典来存储待办事项,键为 todo_id,值为待办事项的内容
TODOS = {
    'todo1': {'task': 'build an API'},
    'todo2': {'task': '?????'},
    'todo3': {'task': 'profit!'},
}
# 定义一个函数来检查待办事项是否存在,如果不存在则抛出 404 错误
def abort_if_todo_doesnt_exist(todo_id):
    if todo_id not in TODOS:
        abort(404, message="Todo {} doesn't exist".format(todo_id))
# 创建一个 RequestParser 实例来解析请求中的参数
parser = reqparse.RequestParser()
parser.add_argument('task')
# 定义一个 Todo 资源类,继承自 flask_restful.Resource
class Todo(Resource):
    # 定义 GET 方法,用于获取指定 todo_id 的待办事项
    def get(self, todo_id):
        abort_if_todo_doesnt_exist(todo_id)
        return TODOS[todo_id]
    # 定义 DELETE 方法,用于删除指定 todo_id 的待办事项
    def delete(self, todo_id):
        abort_if_todo_doesnt_exist(todo_id)
        del TODOS[todo_id]
        return '', 204  # 返回空响应和 204 No Content 状态码
    # 定义 PUT 方法,用于更新指定 todo_id 的待办事项
    def put(self, todo_id):
        args = parser.parse_args()
        task = {'task': args['task']}
        TODOS[todo_id] = task
        return task, 201  # 返回更新后的待办事项和 201 Created 状态码
# 定义一个 TodoList 资源类,继承自 flask_restful.Resource
class TodoList(Resource):
    # 定义 GET 方法,用于获取所有待办事项的列表
    def get(self):
        return TODOS
    # 定义 POST 方法,用于添加新的待办事项
    def post(self):
        args = parser.parse_args()
        todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
        todo_id = 'todo%i' % todo_id
        TODOS[todo_id] = {'task': args['task']}
        return TODOS[todo_id], 201  # 返回新添加的待办事项和 201 Created 状态码
# 添加资源路由到 API
api.add_resource(TodoList, '/todos')  # 将 TodoList 资源映射到 /todos 路径
api.add_resource(Todo, '/todos/<todo_id>')  # 将 Todo 资源映射到 /todos/<todo_id> 路径
# 当此脚本作为主程序运行时,执行以下代码
if __name__ == '__main__':
    # 启动 Flask 应用,开启 debug 模式以提供调试信息
    app.run(debug=True)

这个应用定义了两个资源:TodoTodoListTodo 资源允许用户获取、删除和更新特定的待办事项,而 TodoList 资源允许用户获取所有待办事项的列表和添加新的待办事项。待办事项的数据存储在全局字典 TODOS 中。应用运行后,可以通过发送 HTTP 请求到指定的 URL 来与资源进行交互。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/518405.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】模拟实现红黑树(插入)

目录 红黑树的概念 红黑树的性质 红黑树的调整情况 红黑树的模拟实现 枚举类型的定义 红黑树节点的定义 插入函数的实现 旋转函数的实现 左旋 右旋 自检函数的实现 红黑树类 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储…

数据结构进阶篇 之 【并归排序】(递归与非递归实现)详细讲解

都说贪小便宜吃大亏&#xff0c;但吃亏是福&#xff0c;那不就是贪小便宜吃大福了吗 一、并归排序 MergeSort 1.基本思想 2.实现原理 3.代码实现 4.归并排序的特性总结 二、非递归并归排序实现 三、完结撒❀ –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀…

Leetcode链表刷题总结(Java版)

链表 1、移除链表元素&#xff08;考虑全情况&#xff09; 问题需求&#xff1a;根据给定的val值&#xff0c;移除链表中值是这个val的节点 203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 这里有一个问题就是&#xff0c;如果需要被移除的节点不是中间的某个节点…

【蓝桥杯嵌入式】六、真题演练(二)-1研究篇:第 13 届真题-第二部分

温馨提示&#xff1a; 真题演练分为模拟篇和研究篇。本专栏的主要作用是记录我的备赛过程&#xff0c;我打算先自己做一遍&#xff0c;把遇到的问题和不同之处记录到演练篇&#xff0c;然后再返回来仔细研究一下&#xff0c;找到最佳的解题方法记录到研究篇。题目在&#xff1a…

【CSS】浮动笔记及案例

CSS浮动 1. 认识浮动 float属性可以指定一个元素沿着左侧或者是右侧放置&#xff0c;允许文本和内联元素环绕它 float属性最初只使用文字环绕图片但却是早起CSS最好用的左右布局方案 绝对定位、浮动都会让元素脱标&#xff0c;以达到灵活布局的目的可以通过float属性让元素脱…

SSM实战项目——哈哈音乐(二)后台模块开发

1、项目准备 ① 引入后台模块&#xff08;hami-console&#xff09;需要的依赖 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0…

【Qt】:常用控件(五:显示类控件)

常用控件 一.ProgressBar二. Calendar Widget 一.ProgressBar 使⽤ QProgressBar 表⽰⼀个进度条 代码⽰例:设置进度条按时间增⻓ 设置定时器&#xff0c;每个0.1秒&#xff0c;让进度条1 在实际开发中&#xff0c;进度条的取值&#xff0c;往往是根据当前任务的实际进度来进行…

创意绘图画画小程序:融合白板黑板功能,开启绘画新纪元

创意绘图画画小程序&#xff1a;融合白板黑板功能&#xff0c;开启绘画新纪元 在数字化时代的浪潮下&#xff0c;艺术创作正逐渐摆脱传统形式的束缚&#xff0c;以更加多元、便捷的方式走进人们的生活。其中&#xff0c;创意绘图画画小程序以其独特的白板画、黑板画功能&#…

蓝桥杯真题:k倍区间

import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int k sc.nextInt();int[] a new int[n];long[] v new long[200000];long…

【注册中心】ZooKeeper

文章目录 概述Zookeeper的应用场景Zookeeper的角色Zookeeper 的数据模型zookeeper客户端常用命令Zookeeper的核心功能Zookeeper的架构与集群规则Zookeeper的工作模式Zookeeper如何实现分布式锁Zookeeper JavaAPI&#xff08;Curator&#xff09;来源 概述 Zookeeper 是一个开源…

手写防抖节流、手写深拷贝、事件总线

一、防抖 手写防抖--基本实现&#xff08;面试&#xff09; 手写防抖并且绑定this和event 添加取消功能 添加立即执行状态&#xff0c;默认不立即执行 underscore库介绍&#xff0c;lodash更轻量级 二、节流 用underscore库&#xff0c;调用throttle函数 手写基础版节流-&#…

Spring重点知识(个人整理笔记)

目录 1. 为什么要使用 spring&#xff1f; 2. 解释一下什么是 Aop&#xff1f; 3. AOP有哪些实现方式&#xff1f; 4. Spring AOP的实现原理 5. JDK动态代理和CGLIB动态代理的区别&#xff1f; 6. 解释一下什么是 ioc&#xff1f; 7. spring 有哪些主要模块&#xff1f;…

数据结构系列-队列的结构和队列的实现

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 队列 队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO&#xff0c;…

Python | Leetcode Python题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; class Solution:def isMatch(self, s: str, p: str) -> bool:m, n len(s), len(p)dp [False] * (n1)# 初始化dp[0] Truefor j in range(1, n1):if p[j-1] *:dp[j] dp[j-2]# 状态更新for i in range(1, m1):dp2 [False] * (n1) …

【C++】排序算法 --快速排序与归并排序

目录 颜色分类&#xff08;数组分三块思想&#xff09;快速排序归并排序 颜色分类&#xff08;数组分三块思想&#xff09; 给定⼀个包含红⾊、⽩⾊和蓝⾊、共 n 个元素的数组 nums &#xff0c;原地对它们进⾏排序&#xff0c;使得相同颜⾊ 的元素相邻&#xff0c;并按照红⾊、…

【面试八股总结】传输控制协议TCP(一)

参考资料 &#xff1a;小林Coding、阿秀、代码随想录 一、什么是TCP协议 TCP是传输控制协议Transmission Control Protocol TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接的&#xff1a;每条TCP连接杜只能有两个端点&#xff0c;每一条TCP连接只能是点对…

js中的事件循环

浏览器进程模型 在理解什么叫事件循环前&#xff0c;我们需要先知道浏览器的进程模型 现代浏览器的功能极度复杂&#xff0c;为了能确保各个部分独立运行互不影响&#xff0c;浏览器会在启动之时开启多个进程&#xff0c;具体而言可以分为以下三种 浏览器进程 负责浏览器的用…

Pulsar服务端处理消费者请求以及源码解析

引言 处理读写是Pulsar服务端最基本也是最重要的逻辑&#xff0c;今天就重点看看服务端是如何处理的读请求也就是消费者请求 正文 Pulsar服务端处理消费者请求的流程大致如下图所示 消费者通过TCP向服务端发起消息拉取请求Broker会根据请求中携带的ID来获取在服务端对应的…

Lua 和 Love 2d 教程 二十一点朴克牌 (上篇lua源码)

GitCode - 开发者的代码家园 Lua版完整原码 规则 庄家和玩家各发两张牌。庄家的第一张牌对玩家是隐藏的。 玩家可以拿牌&#xff08;即拿另一张牌&#xff09;或 停牌&#xff08;即停止拿牌&#xff09;。 如果玩家手牌的总价值超过 21&#xff0c;那么他们就爆掉了。 面牌…

WIFI|软体 茶凳浅谈 高通WIN QSDK - IPQ6000 与 88Q2112 的相遇

Qualcomm IPQ 系列的Ethernet IC 搭配的有 QCA8075, QCA8081 … 等等Qualcomm自家出产的芯片。QSDK中内建可以支持的3rd party芯片&#xff0c;却寥寥可数。日前&#xff0c;客户使用车载以太网 - 88Q2112 - Marvell与IPQ6000做搭配。将之记录下来&#xff0c;以供参考。 方…