Pregunta

Estoy buscando una única solución SQLAlchemy para convertir un dict recibido de envío de un formulario en una serie de filas de la base de datos, una para cada campo presentado. Esto es para manejar las preferencias y configuraciones que varían ampliamente en todas las aplicaciones. Sin embargo, es muy probable que proceda a la creación de tabla dinámica como la funcionalidad. He visto este tipo de cosas en herramientas ETL, pero yo estaba buscando una manera de hacerlo directamente en el ORM. No pude encontrar ninguna documentación sobre el mismo, pero tal vez me haya perdido algo.

Ejemplo:

Enviado de la forma: { "ID Única": 1, "a": 23, "b": "Hola", "c": "Mundial"}

Me gustaría que se transforme (en el ORM) de modo que se registra en la base de datos como esta:

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

Tras un selecto el resultado sería transformado (en el ORM) de nuevo en una fila de datos de cada uno de los valores individuales.

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

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

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

Yo asumiría en una actualización que el mejor curso de acción sería la de envolver un borrado / crear en una transacción por lo que los registros actuales serían retirados y los nuevos insertados.

La relación definitiva de ItemNames se mantendrá en una tabla separada.

Totalmente abierto a soluciones más elegantes, pero le gustaría mantener fuera del lado de la base de datos si es posible.

Estoy usando el enfoque declarative_base con SQLAlchemy.

Gracias de antemano ...

Saludos,

Paul

¿Fue útil?

Solución

Este es un ejemplo ligeramente modificado a partir de documentación trabajar con tal estructura de la tabla asignada al diccionario en el modelo:

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()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top