当前位置: 首页 > 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),通过将所有资产组合在…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)&#xff0…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...