1

我最近一直在使用 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'.

这是可行的吗?还是我会被迫用手动发出的查询来弄乱我的代码?

4

1 回答 1

6

查看垂直属性映射的示例。我认为这或多或少是你所追求的。这些示例提供了一个类似 dict 的界面,而不是您的示例中的属性(对于任意元数据键可能更好,而不是一些特定的属性)。

如果您希望单独映射每个属性:文档中可能感兴趣的内容:

  • sql 表达式作为映射属性:如何将属性映射到任意 sql 表达式(只读)
  • 改变属性行为,尤其是。使用描述符和自定义比较器:这归结为只为您的属性使用普通的 python 属性,并在 get/set 上执行您需要的任何操作 + 可选地规定与其他值(用于查询)的比较需要如何工作。
  • Associationproxy:基本上提供了一个更简单的关系视图。例如,在您的情况下,您可以_age使用自定义连接条件(不仅是用户 ID,而且还指定类型“年龄”)和使用uselist=False(因为有每个用户只有一个年龄,您需要一个值,而不是列表)。然后,您可以使用age = association_proxy('_age', 'value')它使其仅“显示”值,而不是整个 KeyValue 对象。

我想我会选择基于垂直属性映射示例的东西,或者使用 associationproxy/

于 2010-08-03T14:24:47.140 回答