【问题标题】:SQLAlchemy Column to Row Transformation and vice versa -- is it possible?SQLAlchemy 列到行转换,反之亦然——这可能吗?
【发布时间】:2010-01-18 22:24:05
【问题描述】:

我正在寻找一种仅限 SQLAlchemy 的解决方案,用于将从表单提交接收到的 dict 转换为数据库中的一系列行,每个提交的字段一个。这是为了处理跨应用程序差异很大的首选项和设置。但是,它很可能适用于创建类似于数据透视表的功能。我在 ETL 工具中看到过这种类型的事情,但我一直在寻找一种直接在 ORM 中执行此操作的方法。我找不到任何关于它的文档,但也许我错过了一些东西。

例子:

从表单提交:{"UniqueId":1, "a":23, "b":"Hello", "c":"World"}

我希望它被转换(在 ORM 中),以便它像这样记录在数据库中:

_______________________________________
|UniqueId| ItemName   | ItemValue     |
---------------------------------------
|  1     |    a       |    23         |
---------------------------------------
|  1     |    b       |    Hello      |
---------------------------------------
|  1     |    c       |    World      |
---------------------------------------

在选择时,结果将被转换(在 ORM 中)从每个单独的值转换回一行数据。

---------------------------------------------------
| UniqueId  |  a     |     b      |       c       |

---------------------------------------------------
|   1       |  23    |   Hello    |   World       |

---------------------------------------------------

我会假设在更新时最好的做法是将删除/创建包装在事务中,以便删除当前记录并插入新记录。

ItemNames 的最终列表将保存在单独的表中。

对更优雅的解决方案完全开放,但如果可能的话,希望远离数据库。

我在 SQLAlchemy 中使用 declarative_base 方法。

提前谢谢...

干杯,

保罗

【问题讨论】:

    标签: python orm sqlalchemy pivot-table transformation


    【解决方案1】:

    这里是 documentation 的一个稍作修改的示例,用于处理映射到模型中字典的这种表结构:

    from sqlalchemy import *
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm.collections import attribute_mapped_collection
    from sqlalchemy.ext.associationproxy import association_proxy
    from sqlalchemy.orm import relation, sessionmaker
    
    metadata  = MetaData()
    Base = declarative_base(metadata=metadata, name='Base')
    
    class Item(Base):
    
        __tablename__ = 'Item'
        UniqueId = Column(Integer, ForeignKey('ItemSet.UniqueId'),
                          primary_key=True)
        ItemSet = relation('ItemSet')
        ItemName = Column(String(10), primary_key=True)
        ItemValue = Column(Text) # Use PickleType?
    
    def _create_item(ItemName, ItemValue):
        return Item(ItemName=ItemName, ItemValue=ItemValue)
    
    class ItemSet(Base):
    
        __tablename__ = 'ItemSet'
        UniqueId = Column(Integer, primary_key=True)
        _items = relation(Item,
                          collection_class=attribute_mapped_collection('ItemName'))
        items = association_proxy('_items', 'ItemValue', creator=_create_item)
    
    engine = create_engine('sqlite://', echo=True)
    metadata.create_all(engine)
    
    session = sessionmaker(bind=engine)()
    data = {"UniqueId": 1, "a": 23, "b": "Hello", "c": "World"}
    s = ItemSet(UniqueId=data.pop("UniqueId"))
    s.items = data
    session.add(s)
    session.commit()
    

    【讨论】:

    • 出色的丹尼斯!正是我想要的。我还要感谢您添加了一个很好的工作示例。为我节省了很多时间试图理解 Association_proxy 的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    相关资源
    最近更新 更多