在SQLAlchemy中是否可以从表(而不是从映射的类)转储和加载?

时间:2016-07-08 12:22:47

标签: python sqlalchemy pickle

TL; DR 使用SQLAlchemy是否可以使用dumps(…) and load(…)(而不是Table)进行mapped class?为了澄清,我写了two tiny tests (currently red)来表达我的观点。

拥有此映射的类和会话:

<h3>Animals:</h3>
<ul id="animal"></ul>

使用from sqlalchemy import Column, Integer, String, create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.serializer import loads, dumps from sqlalchemy.orm import mapper, scoped_session from sqlalchemy.orm.session import sessionmaker engine = create_engine('sqlite:///:memory:', echo=False) Base = declarative_base(bind=engine) session = scoped_session(sessionmaker()) class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) email = Column(String(140), index=True, unique=True) 映射类我可以转储和加载数据:

User

但使用>>> # create a record >>> Base.metadata.create_all() >>> session.add(User(email='john@alchemydumps')) >>> session.commit() >>> >>> # use dumps >>> with open('dummy_file', 'wb') as file_handler: ... file_handler.write(dumps(session.query(User).all())) ... 490 >>> >>> # reset the database >>> Base.metadata.drop_all() >>> Base.metadata.create_all() >>> >>> # use loads >>> with open('dummy_file', 'rb') as file_handler: ... for row in loads(file_handler.read()): ... session.merge(row) ... <__main__.User object at 0x10977ea20> >>> session.commit() >>> >>> # assert data is back >>> session.query(User).count() 1 >>> 代替工作:

Table

此代码与>>> … >>> >>> # use a table instead (User.__table__, instead of User) >>> with open('dummy_file', 'wb') as file_handler: ... file_handler.write(dumps(session.query(User.__table__).all())) ... 115 >>> Base.metadata.drop_all() >>> Base.metadata.create_all() >>> >>> with open('dummy_file', 'rb') as file_handler: ... for row in loads(file_handler.read()): ... session.merge(row) ...

崩溃
sqlalchemy.orm.exc.UnmappedInstanceError

这条消息已经太长了,所以我避免谈论有关问题的背景。但我确实有a situation我需要转储和加载非映射类......我正试图找到一个解决方案。 (免责声明:2年前,当我是Python的新手时,我写了这个包;是的,代码看起来很糟糕 - 但我在过去几周里一直在完全重构它。

SQLAlchemy中这个新手的任何想法或建议?

1 个答案:

答案 0 :(得分:0)

在@ univerio的评论之后,我可以更好地了解情况并修复,是的!

问题是,如果SQLAlchemy dumps收到Table实例,结果与表无关,则它们纯粹是KeyedTuple。所以我不得不:

  1. KeyedTuple加载
  2. 时引入映射类
  3. KeyedTuple转换为字典(这很简单,因为KeyedTuple_asdict()方法)
  4. 然后合并(因为它原本是我的意图)
  5. tests are now green,但总结一下这就是我所需要的:

    with open('dummy_file', 'rb') as file_handler:
    ...     for row in loads(file_handler.read()):
    ...         if isinstance(row, KeyedTuple):
    ...             row = User(**row._asdict())
    ...         session.merge(row)
    >>> session.commit()