Я пытаюсь использовать 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
«s .Как только у нас есть повторы, мы сталкиваемся с ключами словаря, определенными последним совпадением node_attr
.Каждое последующее значение с тем же ключом закрывает предыдущее значение.
Я бы хотел, чтобы отображаемый словарь Node.attributes
был словарем атрибутов, сопоставленных со списками объектов, как в приведенном выше примере defaultdict.Как я могу это сделать?
Я пытаюсь пролистать документацию, чтобы найти простой способ использования defaultdict(list)
вместо встроенного dict
, но, похоже, мне нужно реализоватьспециальный MappedCollection
класс .К сожалению, документация для этого чрезвычайно запутана, и я совсем не уверен, какие магические методы мне действительно нужно реализовать.Например, в связанном разделе я вижу это:
@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
и поэтому не может быть переопределен для моего варианта использования.
Указания в этомнаправление, если это направление, в котором я должен идти, было бы очень полезно.
Обновление
Я начал мошенничать с обходным путем.
Использование формы.reconstructor Я просто создаю defaultdict при загрузке объекта.Я не думаю, что это вызовет какие-либо проблемы с производительностью, поскольку фактический набор значений довольно мал, вообще говоря, но если есть способ сделать это с помощью SQLA, я бы очень хотел это знать.