Простой ответ: да .
Просто используйте прокси-сервер ассоциации:
from sqlalchemy import Column, Integer, String, Table, create_engine
from sqlalchemy import orm, MetaData, Column, ForeignKey
from sqlalchemy.orm import relation, mapper, sessionmaker
from sqlalchemy.orm.collections import column_mapped_collection
from sqlalchemy.ext.associationproxy import association_proxy
Создание тестовой среды:
engine = create_engine('sqlite:///:memory:', echo=True)
meta = MetaData(bind=engine)
Определить таблицы:
tb_items = Table('items', meta,
Column('id', Integer, primary_key=True),
Column('name', String(20)),
Column('description', String(100)),
)
tb_notes = Table('notes', meta,
Column('id_item', Integer, ForeignKey('items.id'), primary_key=True),
Column('name', String(20), primary_key=True),
Column('value', String(100)),
)
meta.create_all()
Классы (обратите внимание на association_proxy
в классе):
class Note(object):
def __init__(self, name, value):
self.name = name
self.value = value
class Item(object):
def __init__(self, name, description=''):
self.name = name
self.description = description
notes = association_proxy('_notesdict', 'value', creator=Note)
Отображение:
mapper(Note, tb_notes)
mapper(Item, tb_items, properties={
'_notesdict': relation(Note,
collection_class=column_mapped_collection(tb_notes.c.name)),
})
Тогда просто проверьте это:
Session = sessionmaker(bind=engine)
s = Session()
i = Item('ball', 'A round full ball')
i.notes['color'] = 'orange'
i.notes['size'] = 'big'
i.notes['data'] = 'none'
s.add(i)
s.commit()
print i.notes
Это печатает:
{u'color': u'orange', u'data': u'none', u'size': u'big'}
Но есть ли они в таблице заметок?
>>> print list(tb_notes.select().execute())
[(1, u'color', u'orange'), (1, u'data', u'none'), (1, u'size', u'big')]
Работает !! :)