Paw*_*elP 5 python mysql sqlalchemy pyramid
我有一个 Pyramid/SQLAlchemy,MySQL python 应用程序。当我执行原始 SQL INSERT 查询时,没有任何内容写入数据库。但是,在使用 ORM 时,我可以写入数据库。我阅读了文档,阅读了有关 ZopeTransactionExtension 的内容,阅读了很多 SO 问题,但都无济于事。到目前为止没有用的:
transaction.commit()- 没有任何内容写入数据库。我确实意识到 ZopeTransactionExtension 需要此语句,但它在这里并没有发挥作用。dbsession().commit - 不起作用,因为我使用的是 ZopeTransactionExtensiondbsession().close() - 什么都没写dbsession().flush() - 什么都没写mark_changed(session) ——
如果 session.twophase: AttributeError: 'scoped_session' object has没有属性'双相'"
engine.execute(...)我正在寻找如何使用scoped_session(dbsession()在我的代码中)执行原始 SQL
这是我的 SQLAlchemy 设置 ( models/__init__.py)
def dbsession():
assert (_dbsession is not None)
return _dbsession
def init_engines(settings, _testing_workarounds=False):
import zope.sqlalchemy
extension = zope.sqlalchemy.ZopeTransactionExtension()
global _dbsession
_dbsession = scoped_session(
sessionmaker(
autoflush=True,
expire_on_commit=False,
extension=extension,
)
)
engine = engine_from_config(settings, 'sqlalchemy.')
_dbsession.configure(bind=engine)
Run Code Online (Sandbox Code Playgroud)
这是我为隔离问题而编写的python脚本。它类似于发生问题的真实环境。我想要的只是让下面的脚本将数据插入到数据库中:
# -*- coding: utf-8 -*-
import sys
import transaction
from pyramid.paster import setup_logging, get_appsettings
from sc.models import init_engines, dbsession
from sqlalchemy.sql.expression import text
def __main__():
if len(sys.argv) < 2:
raise RuntimeError()
config_uri = sys.argv[1]
setup_logging(config_uri)
aa = init_engines(get_appsettings(config_uri))
session = dbsession()
session.execute(text("""INSERT INTO
operations (description, generated_description)
VALUES ('hello2', 'world');"""))
print list(session.execute("""SELECT * from operations""").fetchall()) # prints inserted data
transaction.commit()
print list(session.execute("""SELECT * from operations""").fetchall()) # doesn't print inserted data
if __name__ == '__main__':
__main__()
Run Code Online (Sandbox Code Playgroud)
有趣的是,如果我这样做:
session = dbsession()
session.execute(text("""INSERT INTO
operations (description, generated_description)
VALUES ('hello2', 'world');"""))
op = Operation(generated_description='aa', description='oo')
session.add(op)
Run Code Online (Sandbox Code Playgroud)
然后第一个打印输出原始 SQL 插入行 ('hello2' 'world'),第二个打印打印两行,实际上两行都插入到 DB 中。
我无法理解为什么在原始 SQL 旁边使用 ORM 插入来“修复”它。
我真的需要能够在 scoped_session 上调用 execute() 以使用原始 SQL 将数据插入到数据库中。有什么建议吗?
自从我将原始 sql 与 sqlalchemy 混合以来已经有一段时间了,但是每当您混合它们时,您都需要了解 ORM 幕后发生的情况。首先,检查自动提交标志。如果 zope 事务配置不正确,ORM 插入可能会触发提交。
实际上,在查看了 zope 文档之后,手动执行语句似乎需要一个额外的步骤。从他们的自述中:
默认情况下,zope.sqlalchemy 在首次使用会话时将其置于“活动”状态。ORM 写入操作会自动将会话移至“已更改”状态。这避免了不必要的数据库提交。有时需要直接通过SQL与数据库进行交互。无法猜测这样的操作是读还是写。因此,当手动SQL语句写入数据库时,我们必须手动将会话标记为已更改。
>>> session = Session()
>>> conn = session.connection()
>>> users = Base.metadata.tables['test_users']
>>> conn.execute(users.update(users.c.name=='bob'), name='ben')
<sqlalchemy.engine...ResultProxy object at ...>
>>> from zope.sqlalchemy import mark_changed
>>> mark_changed(session)
>>> transaction.commit()
>>> session = Session()
>>> str(session.query(User).all()[0].name)
'ben'
>>> transaction.abort()
Run Code Online (Sandbox Code Playgroud)
看来你没有这样做,所以 transaction.commit 什么也不做。
| 归档时间: |
|
| 查看次数: |
4370 次 |
| 最近记录: |