SQLAlchemy Column to Row Transformation и наоборот - возможно ли это? - PullRequest
4 голосов
/ 19 января 2010

Я ищу единственное решение 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.

Заранее спасибо ...

Приветствия

Пол

1 Ответ

8 голосов
/ 19 января 2010

Вот слегка измененный пример из документации для работы с такой структурой таблицы, сопоставленной со словарем в модели:

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