假设有这样的场景, 某实体在具体条目上, 其属性是不定的, 或者其属性是充分稀疏的:
| id | name | attr_0 | attr_1 | attr_2 | … | attr_n |
|---|---|---|---|---|---|---|
| 1 | foo | 1 | abc | 33 | … | any |
这种情况下, 把属性看成是单独的实体, 是一个更好的建模方式:
| id | name |
|---|---|
| 1 | foo |
| id | entity_id | attr_name | attr_value |
|---|---|---|---|
| 1 | 1 | attr_0 | 1 |
| 2 | 1 | attr_1 | 33 |
| … | … | … | … |
| n | 1 | attr_n | any |
这种模型下, ORM 层面我们考虑封装一个对操作更友好的上层操作接口, 比如:
1 | obj = Entity() |
实现上, 就是把对象的方法, 包装成 SQLAlchemy 的 ORM 中的对应的关系操作.
1 | class BaseModel(declarative_base()): |
实现上就两点:
_attributes 关系中, 指定 collection_class , 于是就可以得到一个像 dict 的属性对象了.association_proxy 从 dict的属性对象中只抽出我们关心的 value 属性值.
这个场景中, 还可以再进一步, 在 Entity 类上实现 dict 的一些方法, 直接操作其 attributes 属性, association_proxy 就直接返回 Entity 的实例, 这样代码可以变成这样:
1 | entity = Entity(name=u'ABC') |