~ubuntu-branches/debian/jessie/sqlalchemy/jessie

« back to all changes in this revision

Viewing changes to examples/association/dict_of_sets_with_default.py

  • Committer: Bazaar Package Importer
  • Author(s): Piotr Ożarowski
  • Date: 2011-08-01 23:18:16 UTC
  • mfrom: (1.4.15 upstream) (16.1.14 experimental)
  • Revision ID: james.westby@ubuntu.com-20110801231816-6lx797pi3q1fpqst
Tags: 0.7.2-1
* New upstream release
* Bump minimum required python-mako version to 0.4.1 (closes: 635898)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Illustrate a 'dict of sets of integers' model.
 
2
 
 
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.
 
9
 
 
10
"""
 
11
 
 
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
 
17
import operator
 
18
 
 
19
class Base(object):
 
20
    id = Column(Integer, primary_key=True)
 
21
 
 
22
Base = declarative_base(cls=Base)
 
23
 
 
24
class GenDefaultCollection(MappedCollection):
 
25
    def __missing__(self, key):
 
26
        self[key] = b = B(key)
 
27
        return b
 
28
 
 
29
class A(Base):
 
30
    __tablename__ = "a"
 
31
    associations = relationship("B",
 
32
        collection_class=lambda: GenDefaultCollection(operator.attrgetter("key"))
 
33
    )
 
34
 
 
35
    collections = association_proxy("associations", "values")
 
36
    """Bridge the association from 'associations' over to the 'values'
 
37
    association proxy of B.
 
38
    """
 
39
 
 
40
class B(Base):
 
41
    __tablename__ = "b"
 
42
    a_id = Column(Integer, ForeignKey("a.id"), nullable=False)
 
43
    elements = relationship("C", collection_class=set)
 
44
    key = Column(String)
 
45
 
 
46
    values = association_proxy("elements", "value")
 
47
    """Bridge the association from 'elements' over to the 
 
48
    'value' element of C."""
 
49
 
 
50
    def __init__(self, key, values=None):
 
51
        self.key = key
 
52
        if values:
 
53
            self.values = values
 
54
 
 
55
class C(Base):
 
56
    __tablename__ = "c"
 
57
    b_id = Column(Integer, ForeignKey("b.id"), nullable=False)
 
58
    value = Column(Integer)
 
59
    def __init__(self, value):
 
60
        self.value = value
 
61
 
 
62
if __name__ == '__main__':
 
63
    engine = create_engine('sqlite://', echo=True)
 
64
    Base.metadata.create_all(engine)
 
65
    session = Session(engine)
 
66
 
 
67
    # only "A" is referenced explicitly.  Using "collections",
 
68
    # we deal with a dict of key/sets of integers directly.
 
69
 
 
70
    session.add_all([
 
71
        A(collections={
 
72
            "1":set([1, 2, 3]),
 
73
        })
 
74
    ])
 
75
    session.commit()
 
76
 
 
77
    a1 = session.query(A).first()
 
78
    print a1.collections["1"]
 
79
    a1.collections["1"].add(4)
 
80
    session.commit()
 
81
 
 
82
    a1.collections["2"].update([7, 8, 9])
 
83
    session.commit()
 
84
 
 
85
    print a1.collections["2"]
 
86
 
 
87