我正在寻找一种SQLAlchemy唯一解决方案,用于将从表单提交收到的字典转换为数据库中的一系列行,每个字段用于提交的每个字段。这是为了处理各种应用程序差异很大的首选项和设置。但是,它很可能适用于创建类似功能的数据透视表。我在ETL工具中看到过这种类型的东西,但我一直在寻找一种直接在ORM中完成它的方法。我找不到任何关于它的文件,但也许我错过了一些东西。
示例:
从表格提交:{“UniqueId”: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方法。
提前致谢...
干杯,
保
答案 0 :(得分: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()