Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Custom MappedCollection example for SQLAlchemy returning a dict of lists
from sqlalchemy import Model, Column, Integer, ForeignKey, String, Text
from orm_helpers import KeyedListCollection
class ItemAttribute(Model):
__tablename__ = 'item_attributes'
id = Column(Integer, primary_key=True, autoincrement=True)
item_id = Column(Integer, ForeignKey('items.id'))
attribute = Column(String(255))
value = Column(Text)
class Item(Model):
__tablename__ = 'items'
id = Column(Integer, primary_key=True, autoincrement=True)
attributes = db.relationship(ItemAttribute,
collection_class=lambda: KeyedListCollection('attribute'),
cascade='all, delete-orphan')
"""This relationship allows you to access your attributes as a list of ItemAttribute objects,
keyed off their `attribute` value. So `item.attributes` might return something like this:
{
'title': [ <ItemAttribute attribute="title" value="Example"> ]
'features': [
<ItemAttribute attribute="features" value="Hello">,
<ItemAttribute attribute="features" value="World">
]
}
"""
import operator
from sqlalchemy.orm.collections import MappedCollection, collection
class KeyedListCollection(MappedCollection):
"""This transforms a collection of attribute values into a dict of lists.
This is useful when representing an EAV table, for instance, because
any given attribute can have multiple values, but it is typically
most useful to access them by attribute name.
"""
def __init__(self, key):
super(KeyedListCollection, self).__init__(operator.attrgetter(key))
@collection.internally_instrumented
def __setitem__(self, key, value, _sa_initiator=None):
if not super(KeyedListCollection, self).get(key):
super(KeyedListCollection, self).__setitem__(key, [], _sa_initiator)
super(KeyedListCollection, self).__getitem__(key).append(value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.