Anu*_*wal 12 python activerecord design-patterns datamapper flask-sqlalchemy
我最近开始研究Flask和Flask-SQLAlchemy.来自Django背景我发现Flask-SQLAlchmey非常复杂.我已经读过,SQLAlchemy实现了Data Mapper模式,而Django ORM则基于Active Record Pattern.
下面是一个编写的示例代码,它实现了访问数据库的存储库模式.
这是S.Lott(271k声誉)评论的另一个链接,他说ORM是数据访问层,它与模型分开.
我的问题是这些:
Question.query.filter_by(text = text).all()不比使用更好
db.session.query(Question).filter(Question.text == text).all()?这不是DataMapper与ActiveRecord模式的重复,因为这只是告诉定义,我对实际例子更感兴趣.
小智 7
完全同意上面的答案:是的,SQLAlchemy 的数据映射器模式确实更灵活,对于复杂的查询,它确实更强大,更少神奇并且更受控制。
但是,在简单的任务中,例如CRUD,SQLAlchemy 的代码变得过于超重/过多/冗余。
例如,要在最简单的“创建”控制器中创建一些对象,您需要如下所示:
user = User(name='Nick', surname='Nickson')
session.add(user)
session.flush()
Run Code Online (Sandbox Code Playgroud)
而在 Active Record ORM 中,您只需要单个字符串。
好吧,对于简单的任务,我们中的一些人可能想要更简单的东西。我的意思是,拥有 SQLAlchemy 的 Active Record 会很酷。
好消息:我最近为此创建了包(它还包含其他有用的东西)。
查看: https: //github.com/absent1706/sqlalchemy-mixins
一点一点。
我有一个遗留数据库,我必须为它编写一些数据处理实用程序。使用 Mapper 模式,没有 ORM / ActiveRecord 样式,让我在编写查询时像 ActiveRecord 一样简单。它在类似于 SQL 子句的可组合对象上运行,不受 SQL 注入的影响。
“被动”的对象允许更大的灵活性/一致性:复杂连接的结果是命名元组,就像简单选择的结果一样。没有要关心的身份,没有具有相同身份的缓存对象。
所有更新都是明确的;不是对其他地方更改的某些状态的“保存”,没有运行挂钩.save()等。这使得高效的批量更新变得微不足道,如果将正确的数据发送到数据库,则不会出现问题。在我的情况下,两者都是好处。在一般情况下,“视情况而定”。例如,我必须在插入后手动获取数据库生成的 ID。显式运行此查询需要一些额外的工作。在我的情况下,能够在一个查询中而不是每个记录中完成一个查询是一个巨大的福音。
SQLAlchemy 具有分层设计,允许您访问较低的“映射器”级别,即使您在较高的 ORM 级别声明内容并正常对其进行操作。例如,在 Django 中,如果/何时仍然可能,它就不是那么简单了。
在这个例子中,“repository”看起来像一个构建在“mapper”之上的关卡。存储库可以构建在普通 DBAPI 之上,但映射器使一些事情变得更简单,例如更好的参数绑定、结果集的命名元组,以及带有可组合、可重用部分的普通 SQL 之上的包装器。
映射器还提供了一定程度的数据库独立性。例如,SQL Server 和 Postgres 有不同的连接字符串的方法;映射器提供了统一的接口。
你写你select在哪里使用它。如果你有一个你经常在不同上下文中重用的选择,你可以把它放到一个方法或函数中。大多数选择只有一种用途,并且是在现场建造的。
SQLAlchemy 设计的一个很好的特性是您可以轻松存储条件和整个where子句,并在选择/更新/删除语句中重用它们。
Question.query.filter_by(text = text).all()使用隐式事务。
db.session.query(Question).filter(Question.text == text).all()使用显式事务。
显式事务让您安心使用 DML。select当您查询快速变化的数据库并希望您的几个相关selects 看到相同的一致状态时,它们对s 也很重要。
我通常会写一个简单的包装器sessionmaker并编写如下内容:
with my_database.transaction() as trans:
records = trans.query(...)
...
updated = trans.execute(...).rowcount
# Here the transaction commits if all went well.
Run Code Online (Sandbox Code Playgroud)
当我确定不应该在这个块中运行 DML 时,我使用.readonly_transaction()它总是回滚。
在许多情况下,隐式事务很好。Django 允许你装饰一个方法@transaction.atomic并拥有一个半显式的事务控制,在 99% 的情况下就足够了。但有时您需要更细的粒度。
| 归档时间: |
|
| 查看次数: |
3967 次 |
| 最近记录: |