Недавно я работал с Pylons и очень похож на модель SQLAlchemy для взаимодействия с базой данных. Там одна часть моего веб-сайта, хотя я думаю, может извлечь выгоду из схемы EAV.
Использование этого в качестве примера моей таблицы:
id | userid | type | value
---+--------+--------|------------
1 | 1 | phone | 111 111 111
---+--------+--------|------------
2 | 1 | age | 40
Я могу вручную запускать запросы, подобные приведенным ниже, для извлечения и обновления данных:
SELECT value FROM table WHERE userid=1 AND type='phone'
UPDATE table SET value=41 WHERE userid=1 AND type='age'
Это легко и работает... Но ручное построение запросов - это не мой предпочтительный подход. Я хочу использовать SQLAlchemy для создания моей модели таблицы и позволить ей выполнять всю работу с ногами.
Если бы я использовал стандартную схему, в которой каждый type
имел свой собственный столбец, я мог бы сделать следующее:
class People(Base):
__tablename__ = 'people'
id = Column(Integer, primary_key=True)
userid = Column(Integer, ForeignKey('users.id'))
phone = Column(Unicode(40))
age = Column(Integer)
Затем я мог бы вытащить данные, используя:
data = Session.query(People).filter_by(id=1).first()
print data.age
Я хочу иметь возможность сделать то же самое для моей схемы EAV. Итак, в основном, мне нужен способ расширить SQLAlchemy и сказать, что когда я вызываю data.age
, что на самом деле означает, я хочу SELECT value FROM table WHERE id=1 AND type='age'
.
Это выполнимо? Или я буду вынужден загромождать код с запросами вручную?
Посмотрите примеры вертикальное сопоставление атрибутов. Я думаю, что это более или менее то, что вам нужно. В примерах представлен интерфейс типа dict, а не атрибуты, как в вашем примере (вероятно, лучше для любых ключей метаданных, а не для нескольких конкретных атрибутов).
Если вы предпочитаете сопоставлять каждый атрибут отдельно: материал в документах, которые могут представлять интерес:
_age
отношение к вашему KeyValue (или тому, что вы хотите назвать), используя настраиваемое условие соединения (не только userid, но также определяющее тип "возраст" ), и используя uselist=False
(потому что для пользователя есть только один возраст, вам нужно одно значение, а не список). Затем вы можете использовать age = association_proxy('_age', 'value')
, чтобы "показать" только значение, а не весь объект KeyValue.Я полагаю, что я бы пошел либо с чем-то, основанным на примере вертикального сопоставления атрибутов, либо с помощью ассоциациипрокси/