我正在尝试使用将属性映射到具有该属性的对象列表的attribute_mapped_collection
。
为了更好地解释这一点,我可以在Python中这样实现:
from collections import defaultdict
my_dict = defaultdict(list)
每次我附加一个特定的键时,它只会创建一个收集 具有相同密钥的项目。这样我们得到
[ins] In [18]: my_dict = defaultdict(list)
[ins] In [19]: my_dict[1].append(1)
[nav] In [20]: my_dict[1].append(2)
[ins] In [21]: my_dict
Out[21]: defaultdict(list, {1: [1, 2]})
在以下情况下,这在sqlalchemy中将非常有用:
class Node(Base):
id = db.Column(db.Integer, primary_key=True)
class Attribute(Base):
id = db.Column(db.Integer, primary_key=True)
node_id = db.Column(db.Integer, db.ForeignKey('node.id'))
node = db.relationship(
'Node',
backref=backref('attributes', collection_class='attribute_mapped_collection('node_attr')))
node_attr = db.Column(db.String) # a string based keyword-attribute
如果所有attributes
都具有唯一的node_attr
,那么这会非常好用 。一旦重复,就会遇到最后一个匹配的node_attr
所定义的字典键。每个具有相同密钥的后续值都将替换先前的值。
我希望映射字典Node.attributes
是映射到对象列表的属性字典,就像上面的defaultdict示例一样。我该怎么办?
我正在尝试浏览文档,以找到一种简单的方法来使用
defaultdict(list)
而不是内置的dict
,但看来我可能必须implement a special MappedCollection
class。不幸的是,关于此的文档非常混乱,而且我完全不确定我真正必须实现哪种魔术方法。例如,在链接的部分中,我看到以下内容:
@collection.internally_instrumented
def __setitem__(self, key, value, _sa_initiator=None):
# do something with key, value
super(MyMappedCollection, self).__setitem__(key, value, _sa_initiator)
@collection.internally_instrumented
def __delitem__(self, key, _sa_initiator=None):
# do something with key
super(MyMappedCollection, self).__delitem__(key, _sa_initiator)
但是我不知道_sa_initiator
是什么。此外,文档
指定:
class sqlalchemy.orm.collections.MappedCollection(keyfunc)¶
Bases: builtins.dict
这暗示MappedCollection
已经基于builtin.dict
,因此在我的用例中不能被覆盖。
如果这是我必须走的方向,对此的指导将不胜感激。
我已经开始作弊了。
使用orm.reconstructor只是在对象的负载上创建defaultdict。我认为这不会造成任何性能问题,因为通常来说,实际的值集很小,但是如果使用SQLA可以做到这一点,我非常想知道。