【发布时间】:2012-11-20 12:50:02
【问题描述】:
我目前有一列包含 HTML 标记。在该标记中,有一个我想存储在新列中的时间戳(以便我可以查询它)。我的想法是在一次迁移中执行以下操作:
- 为数据创建一个可以为空的新列
- 使用 ORM 拉回我需要解析的 HTML
- 对于每一行
- 解析 HTML 以提取时间戳
- 更新 ORM 对象
但是当我尝试运行迁移时,它似乎陷入了无限循环。到目前为止,这是我所得到的:
def _extract_publication_date(html):
root = html5lib.parse(html, treebuilder='lxml', namespaceHTMLElements=False)
publication_date_string = root.xpath("//a/@data-datetime")[0]
return parse_date(publication_date)
def _update_tip(tip):
tip.publication_date = _extract_publication_date(tip.rendered_html)
tip.save()
def upgrade():
op.add_column('tip', sa.Column('publication_date', sa.DateTime(timezone=True)))
tips = Tip.query.all()
map(tips, _update_tip)
def downgrade():
op.drop_column('tip', 'publication_date')
【问题讨论】:
-
你怎么知道它陷入了无限循环?
-
如果
Tip.query没有使用与op相同的会话,那么将有2 个事务,其中SELECT一个卡住等待ALTER TABLE一个提交。无论如何,我认为将 ORM 部分移动到它自己的脚本中更干净,在alembic upgrade之后手动运行。 -
@X-Istence 我不知道它陷入了无限循环。我确实知道该命令永远不会返回。
-
@sayap 我曾考虑过,但这意味着我无法在同一个地方跟踪我的所有数据库升级逻辑。此外,如果 ORM 逻辑有效,那么我可以在迁移中添加另一个结构步骤以创建新列
NOT NULL。如果我能弄清楚如何让 ORM 使用 seameSession作为op.foo方法,我会更喜欢它。 -
我也努力将逻辑放在同一个地方,但前提是我可以使用 SQL 做到这一点。 Alembic 不建议迁移脚本和应用程序代码之间的紧密耦合。虽然我确实看到了你的观点。您可能想尝试先进行查询并构建
id: publication_date的字典,然后使用op.execute()对其进行更新。如果您的 ORM 会话有autocommit=True,我认为第一个事务将在查询后立即关闭,因此不会有重叠事务。
标签: python sqlalchemy alembic