SQLAlchemy 列到行转换,反之亦然——这可能吗?

发布于 2024-08-17 22:34:34 字数 1236 浏览 6 评论 0原文

我正在寻找一种仅 SQLAlchemy 的解决方案,用于将从表单提交收到的字典转换为数据库中的一系列行,每个行对应提交的每个字段。这是为了处理不同应用程序之间差异很大的首选项和设置。但是,它很可能适用于创建类似数据透视表的功能。我在 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 方法。

预先感谢...

干杯,

保罗

I'm looking for a SQLAlchemy only solution for converting a dict received from a form submission into a series of rows in the database, one for each field submitted. This is to handle preferences and settings that vary widely across applications. But, it's very likely applicable to creating pivot table like functionality. I've seen this type of thing in ETL tools but I was looking for a way to do it directly in the ORM. I couldn't find any documentation on it but maybe I missed something.

Example:

Submitted from form: {"UniqueId":1, "a":23, "b":"Hello", "c":"World"}

I would like it to be transformed (in the ORM) so that it is recorded in the database like this:

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

Upon a select the result would be transformed (in the ORM) back into a row of data from each of the individual values.

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

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

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

I would assume on an update that the best course of action would be to wrap a delete/create in a transaction so the current records would be removed and the new ones inserted.

The definitive list of ItemNames will be maintained in a separate table.

Totally open to more elegant solutions but would like to keep out of the database side if at all possible.

I'm using the declarative_base approach with SQLAlchemy.

Thanks in advance...

Cheers,

Paul

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

短暂陪伴 2024-08-24 22:34:34

这是一个稍微修改过的示例,来自文档使用映射到模型中字典的表结构:

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()

Here is a slightly modified example from documentation to work with such table structure mapped to dictionary in model:

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文