I've found out that you can use collections in relationship in order to change the type of return value, specifically I was interested in dictionaries. Documentation gives an example:
class Item(Base):
__tablename__ = 'item'
id = Column(Integer, primary_key=True)
notes = relationship("Note",
collection_class=attribute_mapped_collection('keyword'),
cascade="all, delete-orphan")
class Note(Base):
__tablename__ = 'note'
id = Column(Integer, primary_key=True)
item_id = Column(Integer, ForeignKey('item.id'), nullable=False)
keyword = Column(String)
text = Column(String)
And it works. However I was hoping that it will make list values if there are more than just one key with the same name. But it only puts the last value under unique key name.
Here is an example:
| Note table |
|---------------------|------------------|
| id | keyword |
|---------------------|------------------|
| 1 | foo |
|---------------------|------------------|
| 2 | foo |
|---------------------|------------------|
| 3 | bar |
|---------------------|------------------|
| 4 | bar |
|---------------------|------------------|
item.notes
will return something like this:
{'foo': <project.models.note.Note at 0x7fc6840fadd2>,
'bar': <project.models.note.Note at 0x7fc6840fadd4>}
Where ids of foo and bar objects are 2 and 4 respectively.
What I'm looking for is to get something like this:
{'foo': [<project.models.note.Note at 0x7fc6840fadd1,
<project.models.note.Note at 0x7fc6840fadd2>],
'bar': [<project.models.note.Note at 0x7fc6840fadd3>,
<project.models.note.Note at 0x7fc6840fadd4>]}
Is it possible to get dict of lists from relationship in sqlalchemy?
So, it turns out you can simply inherit MappedCollection and do whatever you like in setitem there.
from sqlalchemy.orm.collections import (MappedCollection,
_SerializableAttrGetter,
collection,
_instrument_class)
#This will ensure that the MappedCollection has been properly
#initialized with custom __setitem__() and __delitem__() methods
#before used in a custom subclass
_instrument_class(MappedCollection)
class DictOfListsCollection(MappedCollection):
@collection.internally_instrumented
def __setitem__(self, key, value, _sa_initiator=None):
if not super(DictOfListsCollection, self).get(key):
super(DictOfListsCollection, self).__setitem__(key, [], _sa_initiator)
super(DictOfListsCollection, self).__getitem__(key).append(value)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With