【问题标题】:SQLAlchemy committing pickle typesSQLAlchemy 提交泡菜类型
【发布时间】:2016-09-15 14:22:15
【问题描述】:

我在 sqlalchemy 中提交对泡菜类型(列表)的更改时遇到问题。它会表现得好像在提交之后什么都没有发生。

这是我尝试提交的函数:

def commit_move(game_id, player, move):
    game = game_query(game_id)
    if player == 'human':
        game.human_spaces.append(move)
    if player == 'ai':
        game.ai_spaces.append(move)
    game.available_spaces.remove(move)
    print game.human_spaces
    print game.ai_spaces
    print game.available_spaces
    print "----"
    session.add(game)
    session.commit()

这是表的设置方式:

class Game(Base):
    __tablename__ = 'game'
    id = Column(Integer, primary_key=True)
    human_spaces = Column(PickleType)
    ai_spaces = Column(PickleType)
    available_spaces = Column(PickleType)

这是我用来测试它的代码:

game_id = create_game()
print game_id
print get_available_spaces(game_id)
print get_human_spaces(game_id)
print get_ai_spaces(game_id)
print "---------"
commit_move(game_id, 'human', 7)
print get_available_spaces(game_id)
print get_human_spaces(game_id)
print get_ai_spaces(game_id)

这是优秀的终端告诉我的:

1
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[]
[]
---------
[7]
[]
[1, 2, 3, 4, 5, 6, 8, 9]
----
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[]
[]

我确定我在这里缺少一些简单的东西,但任何帮助将不胜感激!

【问题讨论】:

  • 您能否为您提出的问题添加更多细节?也许你希望输出是什么?
  • 我的问题是:我该怎么做才能使我对这些列表所做的更改正确提交到数据库?底部的代码块显示了终端中打印的内容。该块的中间部分显示了我想要的值,它们在提交之前是正确的。但是在我提交之后,(底部)它显示数据库中的值没有改变。有什么我想念的吗?我感觉它与 PickleType 有关,但我不完全确定,希望我能从对 sqlalchemy 有更多经验的人那里得到一些反馈。

标签: python sql sqlalchemy commit pickle


【解决方案1】:

问题在于 ORM 不会对可变类型(如列表)内部的更改发出警报。因此,SQLAlchemy 提供了带有 sqlalchemy.ext.mutable 扩展的突变跟踪。

documentation 中的示例,特别是参考sqlalchemy.ext.mutable.MutableList 类,看起来列声明应该去(例如):

human_spaces = Column(MutableList.as_mutable(PickleType))

我引用as_mutable 方法的文档: “这会建立侦听器来检测针对给定类型的 ORM 映射,并将突变事件跟踪器添加到这些映射中。”

【讨论】:

  • 您也可以尝试related answer 最后一行中描述的方法:“确保在修改 PickleType 对象时更新它们的另一种方法是在提交更改之前复制和分配它们。”
【解决方案2】:

我编写了一个包来帮助简化此操作。您可以选择不同的编码,包括pickle,并轻松将对象转储和存储到数据库。它可以连接到sqlalchemy 理解的任何数据库。 SQL表有字典接口,可以存储dill可以序列化的任何类型:

>>> import klepto
>>> db = klepto.archives.sqltable_archive('playgame')
>>> db['human'] = [1,2,3,4]
>>> db['ai'] = [1,2]
>>> db
sqltable_archive('sqlite:///:memory:?table=playgame', {'ai': [1, 2], 'human': [1, 2, 3, 4]}, cached=True)
>>> db.dump()
>>> 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-28
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 2015-11-02
    相关资源
    最近更新 更多