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()
使用db.session.query(Question).filter(Question.text == text).all()
? 这不是DataMapper vs ActiveRecord模式的重复,因为这只是告诉定义,我对实际示例更感兴趣。
逐点。
1。
我有一个遗留数据库,我必须编写一些数据处理实用程序。 使用Mapper模式,不使用ORM / ActiveRecord风格,在编写查询时让我对使用ActiveRecord非常简单。 它运行在类似于SQL子句的很好的可组合对象上,从SQL注入屏蔽掉。
“被动”对象允许更多的灵活性/一致性:复杂连接的结果是一个命名元组,这是简单选择的结果。 没有关心的身份,没有相同身份的缓存对象。
所有更新都是明确的; 不是在别处修改某些状态的“保存”,没有在.save()
上运行的钩子等。这使得有效的批量更新不重要,如果将正确的数据发送到DB,则不会产生麻烦。 两者都对我有利。 一般情况下,“取决于”。 例如,我必须在插入后手动获取数据库生成的ID。 明确运行此查询是一些额外的工作。 能够在一个查询中做到这一点,而不是每个记录一个查询,对我来说是一个巨大的福音。
SQLAlchemy具有分层设计,即使您在ORM上层声明事物并正常操作它,也可以访问较低的“映射器”级别。 例如,在Django中,如果/仍然有可能,它并不那么简单。
2。
在这个例子中,'储存库'看起来像是在'映射器'之上构建的级别。 该存储库可以建立在普通的DBAPI之上,但映射器使一些事情变得更简单,如更好的参数绑定,结果集的命名元组以及包含可组合的可重用部分的普通SQL之上的包装器。
该映射器还提供了一定程度的数据库独立性。 例如SQL Server和Postgres有不同的方式来连接字符串; 该映射器提供了一个统一的界面。
3。
你在你使用它的地方写下你的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
查看相同的一致状态时,它们对于select
也很重要。
我通常会在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%的情况下是足够的。 但有时你需要更细的粒度。
完全同意上面的答案:是的,SQLAlchemy的数据映射器模式更加灵活,对于复杂的查询,它确实更强大,更少魔法和更多控制。
但是,在诸如CRUD之类的简单任务中,SQLAlchemy的代码变得过重/过度/冗余。
例如,要在最简单的“创建”控制器中创建一些对象,您需要如下所示:
user = User(name='Nick', surname='Nickson')
session.add(user)
session.flush()
在Active Record ORM中,您只需要单个字符串。
那么, 对于简单的任务 ,我们中的一些人可能想要更简单的事情。 我的意思是拥有Active Record for SQLAlchemy将会很酷。
好消息:我最近为此创建了一个包(它也包含其他有用的东西)。
检查出来:https://github.com/absent1706/sqlalchemy-mixins
链接地址: http://www.djcxy.com/p/96053.html