RESTful API 架构快速入门 Flask实现

news2025/4/15 19:06:17

RESTful 简介

1.1 为什么要使用 RESTful 架构?

Representational State Transfer(REST)是一种面向资源的架构风格,广泛应用于网络服务的设计和开发。使用RESTful架构有以下几个优点:

  • 简单性和可扩展性: RESTful 架构基于简单的原则和标准,易于理解和实现。它的设计使得系统更具有可扩展性,便于适应不断变化的需求。

  • 松耦合: RESTful 架构支持松耦合,客户端和服务器之间的交互是无状态的,每个请求都包含足够的信息使其独立完成。这促使系统组件之间的独立性,使得修改一个组件不会影响其他组件。

  • 可见性: RESTful 架构通过使用统一的接口,使得资源的状态和操作对客户端可见。这提高了系统的可维护性和可理解性。

1.2 RESTful API 请求设计

设计 RESTful API 请求时应考虑以下几个方面:

  • 资源标识: 每个资源都应有唯一的标识,通常通过 URI(Uniform Resource Identifier)表示。URI应该清晰地指示资源的位置和唯一性。

  • HTTP 方法: 使用 HTTP 方法(GET、POST、PUT、DELETE 等)来表示对资源的不同操作。例如,GET用于获取资源,POST用于创建资源,PUT用于更新资源,DELETE用于删除资源。

  • 请求参数: 可以通过 URI 查询参数、请求头或请求体传递参数。参数的设计应符合标准,易于理解和使用。

1.3 RESTful API 响应设计

设计 RESTful API 响应时需要考虑以下几个方面:

  • 状态码: 使用合适的 HTTP 状态码来表示请求的结果,如200 OK表示成功,404 Not Found表示资源未找到,等等。

  • 响应体: 响应体应包含所请求资源的表示形式,通常使用 JSON 或 XML 格式。这使得数据在客户端和服务器之间的传输更加灵活和可扩展。

  • 超媒体: 使用超媒体作为应用程序状态的引擎,使得客户端可以通过解析响应中的超媒体链接来发现和使用相关资源。

通过合理设计 RESTful API 请求和响应,可以构建出清晰、可维护、可扩展的系统,实现客户端和服务器之间的有效通信。

Flask例子

__init__.py

from flask import Flask 

from .extensions import api, db
from .resources import ns

def create_app():
    app = Flask(__name__)

    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite3"

    api.init_app(app)
    db.init_app(app)

    api.add_namespace(ns)

    return app

api_models.py

# 导入 Flask-Restx 框架的 fields 模块
from flask_restx import fields

# 从自定义的 extensions 模块中导入 api 对象
from .extensions import api

# 定义一个名为 "Student" 的模型,包含 id(整数)、name(字符串)和一个嵌套的 course_model 字段
student_model = api.model("Student", {
    "id": fields.Integer,           # 学生 ID,类型为整数
    "name": fields.String,          # 学生名称,类型为字符串
    #"course": fields.Nested(course_model)  # 嵌套的课程模型字段,该行代码被注释掉了
})

# 定义一个名为 "Course" 的模型,包含 id(整数)、name(字符串)和一个嵌套的 students 字段,是一个学生列表
course_model = api.model("Course", {
    "id": fields.Integer,           # 课程 ID,类型为整数
    "name": fields.String,          # 课程名称,类型为字符串
    "students": fields.List(fields.Nested(student_model))  # 嵌套的学生列表字段
})

# 定义一个名为 "CourseInput" 的模型,用于接收创建课程时的输入数据
course_input_model = api.model("CourseInput", {
    "name": fields.String,          # 课程名称,类型为字符串
})

# 定义一个名为 "StudentInput" 的模型,用于接收创建学生时的输入数据
student_input_model = api.model("StudentInput", {
    "name": fields.String,          # 学生名称,类型为字符串
    "course_id": fields.Integer     # 所属课程的 ID,类型为整数
})

extensions.py

from flask_sqlalchemy import SQLAlchemy 
from flask_restx import Api

api = Api()
db = SQLAlchemy()

models.py

from .extensions import db 

class Course(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), unique=True)
    
    students = db.relationship("Student", back_populates="course")


class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), unique=True)
    course_id = db.Column(db.ForeignKey("course.id"))

    course = db.relationship("Course", back_populates="students")

resources.py

# 导入 Flask-Restx 框架的 Resource 类和 Namespace 类
from flask_restx import Resource, Namespace 

# 导入自定义的 API 模型和数据库模型
from .api_models import course_model, student_model, course_input_model, student_input_model
from .extensions import db
from .models import Course, Student

# 创建一个命名空间对象,用于组织和管理 API 路由
ns = Namespace("api")

# 创建一个处理 "/hello" 路由的 Resource 类
@ns.route("/hello")
class Hello(Resource):
    def get(self):
        return {"hello": "restx"}

# 创建处理 "/courses" 路由的 Resource 类
@ns.route("/courses")
class CourseListAPI(Resource):
    # 使用 course_model 进行响应数据的序列化
    @ns.marshal_list_with(course_model)
    def get(self):
        # 返回所有课程的查询结果
        return Course.query.all()

    # 使用 course_input_model 进行请求数据的验证
    # 使用 course_model 进行响应数据的序列化
    @ns.expect(course_input_model)
    @ns.marshal_with(course_model)
    def post(self):
        # 从请求中获取课程名称,并创建新的课程对象
        course = Course(name=ns.payload["name"])
        # 将新课程对象添加到数据库中
        db.session.add(course)
        # 提交数据库事务
        db.session.commit()
        # 返回创建的课程对象和状态码 201(表示资源创建成功)
        return course, 201

# 创建处理 "/courses/<int:id>" 路由的 Resource 类
@ns.route("/courses/<int:id>")
class CourseAPI(Resource):
    # 使用 course_model 进行响应数据的序列化
    def get(self, id):
        # 根据课程 ID 查询并返回相应的课程对象
        course = Course.query.get(id)
        return course

    # 使用 course_input_model 进行请求数据的验证
    # 使用 course_model 进行响应数据的序列化
    def put(self, id):
        # 根据课程 ID 查询相应的课程对象
        course = Course.query.get(id)
        # 更新课程对象的名称
        course.name = ns.payload["name"]
        # 提交数据库事务
        db.session.commit()
        # 返回更新后的课程对象
        return course

    # 删除指定 ID 的课程对象
    def delete(self, id):
        course = Course.query.get(id)
        db.session.delete(course)
        db.session.commit()
        # 返回空响应体和状态码 204(表示资源删除成功)
        return {}, 204

# 创建处理 "/students" 路由的 Resource 类
@ns.route("/students")
class StudentListAPI(Resource):
    # 使用 student_model 进行响应数据的序列化
    def get(self):
        # 返回所有学生的查询结果
        return Student.query.all()

    # 使用 student_input_model 进行请求数据的验证
    # 使用 student_model 进行响应数据的序列化
    def post(self):
        # 从请求中获取学生名称和所属课程 ID,并创建新的学生对象
        student = Student(name=ns.payload["name"], course_id=ns.payload["course_id"])
        # 将新学生对象添加到数据库中
        db.session.add(student)
        # 提交数据库事务
        db.session.commit()
        # 返回创建的学生对象和状态码 201(表示资源创建成功)
        return student, 201

# 创建处理 "/students/<int:id>" 路由的 Resource 类
@ns.route("/students/<int:id>")
class StudentAPI(Resource):
    # 使用 student_model 进行响应数据的序列化
    def get(self, id):
        # 根据学生 ID 查询并返回相应的学生对象
        student = Student.query.get(id)
        return student

    # 使用 student_input_model 进行请求数据的验证
    # 使用 student_model 进行响应数据的序列化
    def put(self, id):
        # 根据学生 ID 查询相应的学生对象
        student = Student.query.get(id)
        # 更新学生对象的名称和所属课程 ID
        student.name = ns.payload["name"]
        student.course_id = ns.payload["course_id"]
        # 提交数据库事务
        db.session.commit()
        # 返回更新后的学生对象
        return student

    # 删除指定 ID 的学生对象
    def delete(self, id):
        student = Student.query.get(id)
        db.session.delete(student)
        db.session.commit()
        # 返回空响应体和状态码 204(表示资源删除成功)
        return {}, 204

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle(2-6) Backup and Recovery Overview

文章目录 一、基础知识1、Categories of Failures 故障类别2、Causes of Statement Failures 语句失败的原因故障情况Resolutions 决议 3、User Process Failures 用户进程失败故障情况Resolutions 决议 4、Possible User Errors 用户错误类型故障情况Resolutions 决议 5、Inst…

第六届 传智杯初赛B组

文章目录 A. 字符串拼接&#x1f37b; AC code B. 最小差值&#x1f37b; AC code C. 红色和紫色&#x1f37b; AC code D. abb&#x1f37b; AC code E. kotori和素因子&#x1f37b; AC code F. 红和蓝&#x1f37b; AC code &#x1f970; Tips&#xff1a;AI可以把代码从 j…

056-第三代软件开发-软件打包

第三代软件开发-软件打包 文章目录 第三代软件开发-软件打包项目介绍软件打包1 下载 linuxdepoyqt 工具2 安装 linuxdepoyqt3 qmake配置4 打包程序 总结 关键字&#xff1a; Qt、 Qml、 linuxdeployqt、 Ubuntu、 AppImage 项目介绍 欢迎来到我们的 QML & C 项目&…

自建CA实战之 《0x03 代码签名》

自建CA实战之 《0x03 代码签名》 本文针对Windows平台&#xff0c;介绍如何使用自建CA来签发代码签名证书。 之前的文章中&#xff0c;我们介绍了如何自建CA&#xff0c;以及如何使用自建CA来签发Web服务器证书、客户端证书。 本文将介绍如何使用自建CA来签发代码签名证书。…

坚鹏:中国人寿临沂公司当下中国经济形势与寿险业发展机遇培训

中国人寿保险&#xff08;集团&#xff09;公司属国家大型金融保险企业&#xff0c;2016年中国人寿入主广发银行&#xff0c;开启保险、投资、银行三大板块协同发展新格局。2022年&#xff0c;集团公司合并营业收入站稳万亿平台&#xff1b;合并总资产突破6万亿元大关。中国人寿…

基恩士软件的基本操作(五,日志记录与使用)

目录 基恩士是如何保存日志的&#xff1f; 如何使用日志功能 查看DM10的值1秒加1的记录日志 设定id与储存位置 软元件设定&#xff08; 日志ID有10个&#xff08;0~10&#xff09;&#xff0c;每一个ID最多添加512个软元件&#xff09; 设定触发 执行日志的梯形图程序 触…

Windows 7隐藏用户测试

请注意Window 7是在虚拟机上安装的&#xff0c;ip是192.168.0.108。 下边都是在虚拟机Window 7上操作&#xff0c;直到最后远程连接才在自己本机Windows 11上操作。 需要同时按下Windowsr,然后输入cmd&#xff0c;再点击确定。 在命令上里边输入net user可以显示一下用户。 …

单链表原来是这样实现的!

文章目录 前言1. 链表的概念及结构1.1在链表里&#xff0c;每节“车厢”是什么样的呢&#xff1f;1.2为什么还需要指针变量来保存下⼀个节点的位置&#xff1f; 2. 单链表的实现1. 定义结构体(Seqlist)2. 打印函数(SLTPrint)小插曲&#xff0c;创建节点函数CreateNode3. 尾插函…

一种LED驱动专用控制电路

一、基本概述 TM1620是一种LED&#xff08;发光二极管显示器&#xff09;驱动控制专用IC,内部集成有MCU数字接口、数据锁存 器、LED驱动等电路。本产品质量可靠、稳定性好、抗干扰能力强。主要适用于家电设备(智能热 水器、微波炉、洗衣机、空调、电磁炉)、机顶盒、电子称、…

清分系统对账

流程1的问题&#xff1a; 1、通道一天的数据会有多少&#xff0c;有二三十万条交易数据吗&#xff1f; 2、如果数据过大都存到一个Map里面去&#xff0c;机器不得挂了 步骤1总结&#xff1a; 1、通过channelNo获取通道T的数据&#xff0c;因为通道是一天一个文件给过来。在转…

xxljob学习笔记01(小滴课堂)

分布式调度xxl-job源码部署和数据库建立&#xff1a; 在idea中打开安装包&#xff1a; 创建数据库&#xff1a; 建表&#xff1a; 在项目里&#xff1a; 在navicat里运行语句即可&#xff1a; 修改数据库地址和用户名&#xff0c;密码&#xff1a; 配置令牌&#xff0c;不然谁…

WiFi的CSMA/CA竞争窗口流程简述

1、若站点最初有数据要发送&#xff08;不是发送不成功再进行重传的那种&#xff09;&#xff0c;且检测到信道空闲&#xff0c;在等待DIFS后&#xff0c;就发送整个数据帧。 2、否则&#xff0c;站点执行退避算法。一旦检测到信道忙&#xff0c;就冻结退避计时器。只要信道空…

卸载idea2017-2023步骤 (卸载干净)

1. 右击打开软件所在位置 2. 找到卸载程序 Uninstall.exe, 双击打开 3. 开始卸载 4. 注册表删除 打开winR, 输入命令regedit Ctrl F查找 "jetbrain" 删除查找出来的文件夹。卸载干净, 即可安装新idea

【Amazon】基于Amazon提供的托管式EKS通过eksctl命令部署Kubernetes集群

文章目录 一、使用CloudFormation创建堡垒机二、安装AWS CLI命令行工具三、安装eksctl命令行工具四、创建集群角色4.1 集群服务角色创建4.2 集群节点组角色创建 五、创建 EKS集群六、登录EKS控制台七、参考链接 一、使用CloudFormation创建堡垒机 导航至CloudFormation&#xf…

【前沿技术了解】web图形Canvas、svg、WebGL、数据可视化引擎的技术选型

目录 Canvas&#xff1a;HTML5新增 Canvas标签&#xff08;画布&#xff09; 渲染上下文canvas.getContext(contextType[, contextAttributes]) 上下文类型&#xff08;contextType&#xff09; 上下文属性 (contextAttributes) 示例 动画 setInterval(function, delay)…

【go入门】表单

4.1 处理表单的输入 先来看一个表单递交的例子&#xff0c;我们有如下的表单内容&#xff0c;命名成文件login.gtpl(放入当前新建项目的目录里面) <html> <head> <title></title> </head> <body> <form action"/login" meth…

软件介绍01- koodo Reader支持所有电脑平台!

1 软件简介 Koodo Reader软件是一款阅读器&#xff0c;可以阅读各种格式的文档。用来代替kindle。界面简洁&#xff0c;好看&#xff0c;阅读功能强大&#xff0c;而且可以多设备同步。 因为开源&#xff0c;所以免费。而且支持所有电脑平台&#xff01; 支持格式&#xff1a…

kafka2.x常用命令:创建topic,查看topic列表、分区、副本详情,删除topic,测试topic发送与消费

原创/朱季谦 接触kafka开发已经两年多&#xff0c;也看过关于kafka的一些书&#xff0c;但一直没有怎么对它做总结&#xff0c;借着最近正好在看《Apache Kafka实战》一书&#xff0c;同时自己又搭建了三台kafka服务器&#xff0c;正好可以做一些总结记录。 本文主要是记录如…

解密Kafka主题的分区策略:提升实时数据处理的关键

目录 一、Kafka主题的分区策略概述1.1 什么是Kafka主题的分区策略&#xff1f;1.2 为什么分区策略重要&#xff1f; 二、Kafka默认分区策略2.1 Round-Robin分区策略 三、自定义分区策略3.1 编写自定义分区器3.2 最佳实践&#xff1a;如何选择分区策略 四、分区策略的性能考量4.…

FO-like Transformation

参考文献&#xff1a; [RS91] Rackoff C, Simon D R. Non-interactive zero-knowledge proof of knowledge and chosen ciphertext attack[C]//Annual international cryptology conference. Berlin, Heidelberg: Springer Berlin Heidelberg, 1991: 433-444.[BR93] Bellare M…