当前位置: 首页 > news >正文

掌握Python设计模式,SQL Alchemy打破ORM与模型类的束缚

大家好,反转软件组件之间的依赖关系之所以重要,是因为它有助于降低耦合度和提高模块化程度,进而可以提高软件的可维护性、可扩展性和可测试性。

当组件之间紧密耦合时,对一个组件的更改可能会对其他组件产生意想不到的影响,从而导致整个系统中的连锁更改效应。通过反转依赖关系,可以确保组件仅依赖于抽象而不是具体实现来减轻这个问题。

就ORM和模型类而言,反转依赖关系允许ORM和模型类相互独立地发展,有助于使代码更加模块化、更具可维护性。例如,如果数据库模式发生更改,可以更新ORM以反映新的模式,而无需修改模型类。同样,如果想切换到不同的ORM,我们也可以这样做,而无需修改模型类。

此外,反转依赖关系还允许对每个组件进行单独测试,从而使代码更具可测试性。例如,可以为模型类编写单元测试,而无需设置数据库连接,因为模型类并不依赖于ORM。同样可以为ORM编写集成测试,而无需实例化模型类,因为ORM仅依赖于模型类的抽象。

1.代码示例

以下是一个使用Python中的SQLAlchemy反转ORM和模型类之间依赖关系的示例。首先使用元数据定义模式,然后定义模型类,最后使用映射器和关系设置ORM。

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship, mapper
from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy.schema import MetaData# 使用元数据定义模式
metadata = MetaData()class UserTable:@declared_attrdef __tablename__(cls):return cls.__name__.lower() + 's'id = Column(Integer, primary_key=True)name = Column(String)email = Column(String, unique=True)class PostTable:@declared_attrdef __tablename__(cls):return cls.__name__.lower() + 's'id = Column(Integer, primary_key=True)title = Column(String)content = Column(String)user_id = Column(Integer, ForeignKey('users.id'))# 定义模型类
class User:def __init__(self, name, email):self.name = nameself.email = emailclass Post:def __init__(self, title, content, author):self.title = titleself.content = contentself.author = author# 使用映射器和关系设置ORM
engine = create_engine('sqlite:///example.db')
Session = sessionmaker(bind=engine)
Base = declarative_base()class UserORM(Base, UserTable):@propertydef model(self):return User(self.name, self.email)class PostORM(Base, PostTable):@propertydef model(self):return Post(self.title, self.content, self.author.model)author = relationship(UserORM, backref='posts')Base.metadata.create_all(engine)# 在应用程序中使用ORM和模型类
session = Session()# 创建一些用户和帖子
user1 = UserORM(name='Alice', email='alice@example.com')
user2 = UserORM(name='Bob', email='bob@example.com')post1 = PostORM(title='My first post', content='Hello, world!', author=user1)
post2 = PostORM(title='Another post', content='This is a test', author=user2)# 将用户和帖子保存到数据库
session.add(user1)
session.add(user2)session.add(post1)
session.add(post2)session.commit()# 通过电子邮件地址检索用户
user = session.query(UserORM).filter_by(email='alice@example.com').one()
print(user.model.name)  # 打印出 "Alice"# 检索用户的帖子
for post in user.posts:print(post.model.title)  # 打印出 "My first post"

在这段代码中,首先使用元数据定义了模式,并为数据库中的每个表定义了单独的类。然后定义模型类UserPost,它们与相应的数据库表具有相同的属性。

接下来,使用映射器将模型类映射到数据库表,还定义了User模型和Post模型之间的关系,其中User模型具有一个posts属性,该属性是用户的帖子列表。

最后,在应用程序中使用ORM和模型类,创建一些用户和帖子,并将它们保存到数据库中。然后,通过电子邮件地址检索用户并打印他们的姓名,以及检索用户的帖子并打印它们的标题。

通过以这种方式反转ORM和模型类之间的依赖关系,使代码更加解耦且易于维护。我们可以更改数据库模式或ORM实现而不必修改模型类,反之亦然,这使得轻松测试模型类,而无需设置数据库连接。

此外,通过在ORM类中使用model属性来返回相应模型类的实例,进一步反转了依赖关系,因为现在ORM类依赖于模型类,而不是相反。

通过使用元数据定义模式、定义模型类并使用映射器和关系来设置ORM,可以实现ORM和模型类之间的依赖关系反转。通过这种方法,可以使代码更加解耦且易于维护。

2.反转依赖关系

在上面的代码中,通过以下方式实现了ORM和模型类之间的依赖关系反转:

  1. 使用元数据定义数据库模式:创建了一个metadata对象,并使用它来使用SQLAlchemy的表结构定义数据库模式。

  2. 定义模型类:定义了UserPost模型类,它们代表了系统中的实体,并定义这些实体的属性和行为。

  3. 使用映射器和关系设置ORM:使用SQLAlchemy的mapper函数将ORM类映射到第1步中定义的数据库模式。还使用SQLAlchemy的relationship函数定义ORM类之间的关系,例如UserPost之间的一对多关系。

通过这样做,将ORM类与数据库模式和模型类解耦,并使其依赖于SQLAlchemy提供的抽象,例如元数据和映射器函数。这使得修改数据库模式或切换到不同的ORM实现变得更容易,而无需修改模型类。它还使模型类更容易进行测试,因为可以在不需要实例化ORM类或连接到数据库的情况下对其进行隔离测试。

相关文章:

掌握Python设计模式,SQL Alchemy打破ORM与模型类的束缚

大家好,反转软件组件之间的依赖关系之所以重要,是因为它有助于降低耦合度和提高模块化程度,进而可以提高软件的可维护性、可扩展性和可测试性。 当组件之间紧密耦合时,对一个组件的更改可能会对其他组件产生意想不到的影响&#…...

性能分析与调优: Linux 磁盘I/O 观测工具

目录 一、实验 1.环境 2.iostat 3.sar 4.pidstat 5.perf 6. biolatency 7. biosnoop 8.iotop、biotop 9.blktrace 10.bpftrace 11.smartctl 二、问题 1.如何查看PSI数据 2.iotop如何安装 3.smartctl如何使用 一、实验 1.环境 (1)主机 …...

Could not erase files or folders:

IDEA删除 git 的 localChanges 内的文件时,提示Could not erase files or folders:。 确认下这个文件是否被打开,忘记关闭了;关闭后可以被删除。(文件被打开的情况下,用操作系统自带的删除,也无法删除成功…...

算法训练营第四十四天|动态规划:完全背包理论基础 518.零钱兑换II 377. 组合总和 Ⅳ

目录 动态规划:完全背包理论基础Leetcode518.零钱兑换IILeetcode377. 组合总和 Ⅳ 动态规划:完全背包理论基础 文章链接:代码随想录 题目链接:卡码网:52. 携带研究材料 思路:完全背包问题,物品可…...

探索计算机网络:应用层的魅力

在当今数字化时代,计算机网络已成为我们生活和工作中不可或缺的一部分。网络的每一层都扮演着独特而重要的角色,而应用层,作为网络模型中用户最直接接触的部分,其重要性不言而喻。这篇文章旨在深入探索应用层的核心概念、功能以及…...

MySQL 按日期流水号 条码 分布式流水号

有这样一个场景,有多台终端,要获取唯一的流水号,流水号格式是 日期0001形式,使用MySQL的存储过程全局锁实现这个需求。 以下是代码示例。 注:所有的终端连接到MySQL服务器获取流水号,如果获取到的是 “-1”…...

前端导出Excel文件,部分数字前面0消失处理办法

详细导出可以看之前的文章 js实现导出Excel文档_js 通过 接口 导出 xlsx 代码-CSDN博客 今天的问题是导出一些数据时,有些字段是前面带有0的字符串,而导出后再excel中就被识别成了数字 如图本来字符串前面的0 都没了 解决方案 1. 导出的时候在前面加单…...

零基础学Python网络爬虫案例实战 全流程详解 高级进阶篇

零基础学Python网络爬虫案例实战 全流程详解 入门与提高篇 零基础学Python网络爬虫案例实战 全流程详解 高级进阶篇 编辑推荐 本书讲解了Python爬虫技术的高级进阶知识,帮助有一定爬虫基础的读者进一步提高爬虫技术。本书详解了突破反爬机制的常用手段以及Scrapy和…...

第十二届“中关村青联杯”全国研究生数学建模竞赛-A题:水面舰艇编队防空和信息化战争评估模型(续)(附MATLAB代码实现)

目录 5.3.3 问题三的总结 5.4 问题四的模型建立与求解 5.4.1 问题分析 5.4.2 计算方位角和航向角...

bmp图像文件格式超详解

0 BMP简介 BMP(Bitmap-File)图形文件,又叫位图文件,是Windows采用的图形文件格式,在Windows环境下运行的所有图像处理软件都支持BMP图像文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。一个BMP文件由四部分组成: B…...

Unity Meta Quest 一体机开发(十三):【手势追踪】自定义交互事件 EventWrapper

文章目录 📕教程说明📕交互事件概述📕自定义交互逻辑⭐方法一:Inspector 面板赋值⭐方法二:纯代码处理 此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区。这是一个高质量…...

13、Redis高频面试题

1、项目中为什么用Redis 我们项目中之所以选择Redis,主要是因为Redis有下面这些优点: 操作速度快:Redis的数据都保存在内存中,相比于其它硬盘类的存储,速度要快很多数据类型丰富:Redis支持 string&#x…...

Koa学习笔记

1、npm 初始化 npm init -y生成 package.json 文件,记录项目的依赖2、git 初始化 git init生成 .git 隐藏文件夹,.git 的本地仓库创建 .gitignore 文件,添加不提交文件的名称3、创建 ReadMe.md 文件 记录项目笔记4、搭建项目 安装 Koa 框架npm install koa5、编写最基本的…...

HiDataPlus 3.3.2-005 搭建(个人的一点心得体会 x86 平台)

HDP 集群搭建 前置安装 yum -y install createrepo yum install -y lrzsz yum install -y wget yum install -y vim修改当前集群机器的主机名 hostnamectl set-hostname XXX​ 这里的 XXX 就是要设置的当前机器的主机名称。主机名称是集群唯一的,一定不要重复&am…...

【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据

一、前言 目的:借助虚拟串口软件(VSPD)模拟硬件串口发送数据,使用PHP语言实现接收硬件发送的数据。 我这里的需求是连接天平,把天平的称量数据实时的传送到PHP使用。 使用工具:vspd串口调试工具 使用语…...

HNU-数据库系统-作业

数据库系统-作业 计科210X 甘晴void 202108010XXX 第一章作业 10.09 1.(名词解释)试述数据、数据库、数据库管理系统、数据库系统的概念。 数据,是描述事物的符号记录。 数据库(DB),是长期存储在计算机内、有组织、可共享的大量…...

Python基础知识:整理10 异常相关知识

1 异常的捕获 1.1 基础写法 """基本语法:try:可能发生错误的代码except:如果出现异常,将执行的代码""" try:fr open("D:/abc.txt", "r", encoding"utf-8") except:print("出现异常…...

golang并发安全-select

前面说了golang的channel, 今天我们看看golang select 是怎么实现的。 数据结构 type scase struct {c *hchan // chanelem unsafe.Pointer // 数据 } select 非默认的case 中都是处理channel 的 接受和发送,所有scase 结构体中c是用来存储…...

微软Visual Studio产品之Visual C++编程进阶——一维数组(画画版)

我是荔园微风,作为一名在IT界整整25年的老兵,看到不少初学者在学习编程语言的过程中如此的痛苦,我决定做点什么,我小时候喜欢看小人书(连环画),在那个没有电视、没有手机的年代,这是…...

Moonbeam生态项目分析 — — 下一代DeFi协议HydraDX

作者:David 概览 HydraDX是一个基于Substrate区块链框架构建的DeFi协议,旨在为波卡带来大量流动性。HydraDX的特色服务,HydraDX Omnipool,是一种创新的自动化做市商(AMM),通过将所有资产组合在…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

XCTF-web-easyupload

试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

深度学习习题2

1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...