如何将attribute_mapped_collection与defaultdict(list)一起使用?

时间:2019-02-21 19:00:13

标签: python dictionary sqlalchemy defaultdict

我正在尝试使用将属性映射到具有该属性的对象列表的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可以做到这一点,我非常想知道。

0 个答案:

没有答案