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

使用Python设计模式中的SQL Alchemy反转ORM和模型类之间的依赖关系。

微信搜索关注《Python学研大本营》,加入读者群,分享更多精彩

图片

一、为什么反转依赖关系很重要?

图片

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

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

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

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

二、代码示例

以下是一个使用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_attr
    def __tablename__(cls):
        return cls.__name__.lower() + 's'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    email = Column(String, unique=True)

class PostTable:
    @declared_attr
    def __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 = name
        self.email = email

class Post:
    def __init__(self, title, content, author):
        self.title = title
        self.content = content
        self.author = author

# 使用映射器和关系设置ORM
engine = create_engine('sqlite:///example.db')
Session = sessionmaker(bind=engine)
Base = declarative_base()

class UserORM(Base, UserTable):
    @property
    def model(self):
        return User(self.name, self.email)

class PostORM(Base, PostTable):
    @property
    def 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和模型类之间的依赖关系反转。通过这种方法,我们可以使代码更加解耦且易于维护。

三、反转依赖关系

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

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

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

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

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

推荐书单

《Python高效编程——基于Rust语言》

《Python高效编程——基于Rust语言》详细阐述了基于Rust语言的Python高效编程,主要包括从Python的角度认识Rust、使用Rust构建代码、理解并发性、在Python中构建pip模块、为pip模块创建Rust接口、在Rust中使用Python对象、在Rust中使用Python模块、在Rust中构建端到端Python模块、构建Python Flask应用程序、将Rust注入Python Flask应用程序、集成Rust的最佳实践等内容。此外,本书还提供了相应的示例、代码,以帮助读者进一步理解相关方案的实现过程。

本书适合作为高等院校计算机及相关专业的教材和教学参考书,也可作为相关开发人员的自学教材和参考手册。

《Python高效编程——基于Rust语言》icon-default.png?t=N7T8https://item.jd.com/13712917.html

精彩回顾

《编程必备,解析5种常用的Python设计模式》

《6个必知的PyCharm实用技巧》

《Pandas实战:3分钟玩转数据加载技巧,事半功倍(附代码示例)》

《6个神级PyCharm高效插件,编程如虎添翼》

《快速上手,5分钟内完成个性化Python GUI计算器搭建》

《极速数据可视化!7个Pandas绘图函数助你事半功倍》

《PyCharm必备,7个实用插件助你事半功倍》

微信搜索关注《Python学研大本营》,加入读者群,分享更多精彩

访问【IT今日热榜】,发现每日技术热点

  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值