1
"""Illustrate a 'dict of sets of integers' model.
3
This is a three table model which represents a parent table referencing a
4
dictionary of string keys and sets as values, where each set stores a
5
collection of integers. The association proxy extension is used to hide the
6
details of this persistence. The dictionary also generates new collections
7
upon access of a non-existent key, in the same manner as Python's
8
"collections.defaultdict" object.
12
from sqlalchemy import String, Integer, Column, create_engine, ForeignKey
13
from sqlalchemy.orm import relationship, Session
14
from sqlalchemy.orm.collections import MappedCollection
15
from sqlalchemy.ext.declarative import declarative_base
16
from sqlalchemy.ext.associationproxy import association_proxy
20
id = Column(Integer, primary_key=True)
22
Base = declarative_base(cls=Base)
24
class GenDefaultCollection(MappedCollection):
25
def __missing__(self, key):
26
self[key] = b = B(key)
31
associations = relationship("B",
32
collection_class=lambda: GenDefaultCollection(operator.attrgetter("key"))
35
collections = association_proxy("associations", "values")
36
"""Bridge the association from 'associations' over to the 'values'
37
association proxy of B.
42
a_id = Column(Integer, ForeignKey("a.id"), nullable=False)
43
elements = relationship("C", collection_class=set)
46
values = association_proxy("elements", "value")
47
"""Bridge the association from 'elements' over to the
48
'value' element of C."""
50
def __init__(self, key, values=None):
57
b_id = Column(Integer, ForeignKey("b.id"), nullable=False)
58
value = Column(Integer)
59
def __init__(self, value):
62
if __name__ == '__main__':
63
engine = create_engine('sqlite://', echo=True)
64
Base.metadata.create_all(engine)
65
session = Session(engine)
67
# only "A" is referenced explicitly. Using "collections",
68
# we deal with a dict of key/sets of integers directly.
77
a1 = session.query(A).first()
78
print a1.collections["1"]
79
a1.collections["1"].add(4)
82
a1.collections["2"].update([7, 8, 9])
85
print a1.collections["2"]