2010-01-18 78 views
4

我正在寻找一个SQLAlchemy唯一的解决方案,用于将从表单提交中收到的字典转换为数据库中的一系列行,每个字段提交一个字段。这是为了处理各种应用程序之间差异很大的首选项和设置。但是,它很可能适用于创建类似功能的数据透视表。我已经在ETL工具中看到过这种类型的东西,但我正在寻找一种直接在ORM中执行的方法。我找不到任何文件,但也许我错过了一些东西。SQLAlchemy列到行转换,反之亦然 - 是否有可能?

实施例:

从表单提交:{ “唯一ID为”:1, “A”:23, “B”: “你好”, “C”: “世界”}

我想它被转化(在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方法。

在此先感谢...

干杯,

保罗

回答

8

这里是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() 
+0

辉煌的丹尼斯!正是我在找什么。我还想感谢你为我们添加了一个伟大的工作示例。为我节省了很多时间来理解association_proxy的内容。 – PlaidFan 2010-01-20 15:18:09

相关问题