Flask SQLAlchemy数据映射器与活动记录模式

2024-05-23 17:53:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近开始研究烧瓶和烧瓶的炼金术。从Django的背景来看,我发现Flask SQLAlchmey相当复杂。我读过SQLAlchemy实现了数据映射器模式,而DjangoOrm则基于活动记录模式。在

Here是编写的示例代码,它实现了访问数据库的存储库模式。在

Here是S.Lott(271k声誉)评论的另一个链接,他说ORM是数据访问层,它与模型分离。在

我的问题是:

  1. 你能在上面的例子中提供一个实际的用例,还是你自己的一个例子,其中数据映射器模式是有用的?我所读到的每一处都是,数据映射器模式在复杂的情况下很有用,但并没有看到示例。在
  2. 在上面的例子中使用存储库模式和使用数据映射器模式是否相同?在
  3. 数据映射器倡导者是否像示例中那样在不同的类中编写select查询?在
  4. 为什么Question.query.filter_by(text = text).all()不比 db.session.query(Question).filter(Question.text == text).all()?在

这不是DataMapper vs ActiveRecord pattern的重复,因为这只是说明了定义,我对实际例子更感兴趣。在


Tags: 数据djangotextflask示例here烧瓶模式
3条回答

一点一点。在

1.

我有一个遗留数据库,我必须为其编写一些数据处理实用程序。使用Mapper模式,不使用ORM/ActiveRecord样式,使编写查询时与ActiveRecord一样简单。它在类似SQL子句的可组合对象上操作,不受SQL注入的影响。在

“被动”的对象允许更大的灵活性/一致性:复杂连接的结果是命名元组,简单的选择也是这样。没有需要关心的标识,也没有具有相同标识的缓存对象。在

所有更新都是显式的;不是在别处更改的某个状态的“保存”,也没有在.save()上运行钩子,等等。这使得高效的批处理更新变得微不足道,如果正确的数据被发送到数据库,则不会带来麻烦。对我来说这两个都是好处。一般情况下,“视情况而定”。例如,我必须在插入之后手动获取数据库生成的id。显式地运行这个查询是一项额外的工作。在我的例子中,能够在一个查询而不是每个记录中执行一个查询是一个巨大的好处。在

SQLAlchemy有一个分层设计,允许您访问较低的“mapper”级别,即使您在较高的ORM级别上声明内容并对其进行正常操作。例如,在Django中,如果/当仍然可能的话,就不那么简单了。在

2.

在本例中,“repository”看起来像是构建在“mapper”之上的。存储库本可以构建在纯DBAPI之上,但映射器使一些事情变得更简单,比如更好的参数绑定、为结果集命名的元组,以及在普通SQL之上使用可组合、可重用部分的包装器。在

映射器还提供了一定程度的数据库独立性。E、 SQL Server和Postgres有不同的方式连接字符串;映射器提供统一的接口。在

3.

你可以在使用它的地方写你的select。如果您有一个在不同上下文中经常重用的select,则可以将其放入一个方法或函数中。大多数选择都有一个用途,都是在现场构建的。在

SQLAlchemy设计的一个很好的特性是可以轻松地存储条件和整个where子句,并在select/update/delete语句之间重用它们。在

4.

Question.query.filter_by(text = text).all()使用隐式事务。 db.session.query(Question).filter(Question.text == text).all()使用显式事务。在

显式的交易可以让你安心使用DML。当您查询一个快速变化的数据库并希望您的几个相关的select看到相同的一致状态时,selects也很重要。在

我通常会在sessionmaker周围编写一个简单的包装器,并这样写:

with my_database.transaction() as trans:
   records = trans.query(...)
   ...
   updated = trans.execute(...).rowcount
# Here the transaction commits if all went well.

当我确定不应该在这个块中运行DML时,我使用总是回滚的.readonly_transaction()。在

在许多情况下,隐式事务是可以的。Django允许您用@transaction.atomic修饰方法,并具有半显式事务控制,在99%的情况下足够了。但有时你需要更精细的粒度。在

  1. 我之所以使用datamapper而不是activerecord的唯一原因是如果您有严重的可伸缩性问题。datamapper鼓励分离域对象和数据库访问逻辑,而activerecords将数据库访问逻辑放在域对象中。例如,当您提升Flask实例时,它将只在需要时连接到数据库,而在Django中,它将始终连接到数据库。

  2. 数据映射器将域对象与数据库访问逻辑隔离开来,而存储库模式是域对象和数据映射器之间的一层。它比数据映射器高一级。例如,在数据映射器模式中,您将拥有直接的getter和setter,在repository模式中,您将拥有可能还包含一些复杂业务逻辑的getter和setter。

  3. 数据映射器与模型类分离。只有活动记录模式连接同一类中的getter和setter。

  4. 我已经使用SQLAlchemy和Django一段时间了,我肯定更喜欢类似Django的查询。对于我自己的项目,我使用Flask+SQLAlchemy而不是Django的可能性几乎为零。在考虑这两个框架时,生产力和社区是两个最具决定性的因素。

完全同意上面的答案:是的,SQLAlchemy的数据映射器模式确实更灵活,对于复杂的查询,它确实更强大、更不神奇、更易于控制。在

但是,在诸如CRUD这样的简单任务中,SQLAlchemy的代码变得过于超重/过度/冗余。在

例如,要在最简单的“创建”控制器中创建某个对象,您需要如下所示:

user = User(name='Nick', surname='Nickson')
session.add(user)
session.flush()

在活动记录ORM中,您只需要一个字符串。在

好吧,对于简单的任务,我们中的一些人可能想要更简单的东西。 我的意思是拥有SQLAlchemy的活动记录会很酷。在

好消息:我最近为此创建了一个包(它还包含其他有用的东西)。在

看看:https://github.com/absent1706/sqlalchemy-mixins

相关问题 更多 >