| 1 | """ |
|---|
| 2 | test one to many relationships |
|---|
| 3 | """ |
|---|
| 4 | |
|---|
| 5 | from elixir import * |
|---|
| 6 | from sqlalchemy import and_ |
|---|
| 7 | from sqlalchemy.ext.orderinglist import ordering_list |
|---|
| 8 | |
|---|
| 9 | def setup(): |
|---|
| 10 | metadata.bind = 'sqlite:///' |
|---|
| 11 | |
|---|
| 12 | class TestOneToMany(object): |
|---|
| 13 | def teardown(self): |
|---|
| 14 | cleanup_all(True) |
|---|
| 15 | |
|---|
| 16 | def test_simple(self): |
|---|
| 17 | class A(Entity): |
|---|
| 18 | name = Field(String(60)) |
|---|
| 19 | bs = OneToMany('B') |
|---|
| 20 | |
|---|
| 21 | class B(Entity): |
|---|
| 22 | name = Field(String(60)) |
|---|
| 23 | a = ManyToOne('A') |
|---|
| 24 | |
|---|
| 25 | setup_all(True) |
|---|
| 26 | |
|---|
| 27 | a1 = A(name='a1') |
|---|
| 28 | b1 = B(name='b1', a=a1) |
|---|
| 29 | |
|---|
| 30 | # does it work before a commit? (does the backref work?) |
|---|
| 31 | assert b1 in a1.bs |
|---|
| 32 | |
|---|
| 33 | session.commit() |
|---|
| 34 | session.clear() |
|---|
| 35 | |
|---|
| 36 | b = B.query.one() |
|---|
| 37 | a = b.a |
|---|
| 38 | |
|---|
| 39 | assert b in a.bs |
|---|
| 40 | |
|---|
| 41 | def test_selfref(self): |
|---|
| 42 | class Person(Entity): |
|---|
| 43 | name = Field(String(30)) |
|---|
| 44 | |
|---|
| 45 | father = ManyToOne('Person', inverse='children') |
|---|
| 46 | children = OneToMany('Person', inverse='father') |
|---|
| 47 | |
|---|
| 48 | setup_all(True) |
|---|
| 49 | |
|---|
| 50 | grampa = Person(name="Abe") |
|---|
| 51 | homer = Person(name="Homer") |
|---|
| 52 | bart = Person(name="Bart") |
|---|
| 53 | lisa = Person(name="Lisa") |
|---|
| 54 | |
|---|
| 55 | grampa.children.append(homer) |
|---|
| 56 | homer.children.append(bart) |
|---|
| 57 | lisa.father = homer |
|---|
| 58 | |
|---|
| 59 | session.commit() |
|---|
| 60 | session.clear() |
|---|
| 61 | |
|---|
| 62 | p = Person.get_by(name="Homer") |
|---|
| 63 | |
|---|
| 64 | print "%s is %s's child." % (p.name, p.father.name) |
|---|
| 65 | print "His children are: %s." % ( |
|---|
| 66 | " and ".join([c.name for c in p.children])) |
|---|
| 67 | |
|---|
| 68 | assert p in p.father.children |
|---|
| 69 | assert p.father is Person.get_by(name="Abe") |
|---|
| 70 | assert p is Person.get_by(name="Lisa").father |
|---|
| 71 | |
|---|
| 72 | def test_multiple_selfref(self): |
|---|
| 73 | # define a self-referential table with several relations |
|---|
| 74 | |
|---|
| 75 | class TreeNode(Entity): |
|---|
| 76 | name = Field(String(50), required=True) |
|---|
| 77 | |
|---|
| 78 | parent = ManyToOne('TreeNode') |
|---|
| 79 | children = OneToMany('TreeNode', inverse='parent') |
|---|
| 80 | root = ManyToOne('TreeNode') |
|---|
| 81 | |
|---|
| 82 | def __str__(self): |
|---|
| 83 | return self._getstring(0) |
|---|
| 84 | |
|---|
| 85 | def _getstring(self, level): |
|---|
| 86 | s = ' ' * level + \ |
|---|
| 87 | "%s (%s,%s,%s, %d)" % (self.name, self.id, self.parent_id, |
|---|
| 88 | self.root_id, id(self)) + \ |
|---|
| 89 | '\n' |
|---|
| 90 | s += ''.join([n._getstring(level+1) for n in self.children]) |
|---|
| 91 | return s |
|---|
| 92 | |
|---|
| 93 | setup_all(True) |
|---|
| 94 | |
|---|
| 95 | node2 = TreeNode(name='node2') |
|---|
| 96 | node2.children.append(TreeNode(name='subnode1')) |
|---|
| 97 | node2.children.append(TreeNode(name='subnode2')) |
|---|
| 98 | node = TreeNode(name='rootnode') |
|---|
| 99 | node.children.append(TreeNode(name='node1')) |
|---|
| 100 | node.children.append(node2) |
|---|
| 101 | node.children.append(TreeNode(name='node3')) |
|---|
| 102 | |
|---|
| 103 | session.commit() |
|---|
| 104 | session.clear() |
|---|
| 105 | |
|---|
| 106 | root = TreeNode.get_by(name='rootnode') |
|---|
| 107 | print root |
|---|
| 108 | |
|---|
| 109 | def test_viewonly(self): |
|---|
| 110 | class User(Entity): |
|---|
| 111 | two_blurbs = OneToMany('Blurb', primaryjoin=lambda: |
|---|
| 112 | and_(Blurb.user_id == User.id, Blurb.position < 2), |
|---|
| 113 | viewonly=True |
|---|
| 114 | ) |
|---|
| 115 | blurbs = OneToMany('Blurb', |
|---|
| 116 | collection_class=ordering_list('position'), |
|---|
| 117 | order_by='position') |
|---|
| 118 | |
|---|
| 119 | class Blurb(Entity): |
|---|
| 120 | user = ManyToOne('User') |
|---|
| 121 | position = Field(Integer) |
|---|
| 122 | blurb = Field(Unicode(255)) |
|---|
| 123 | |
|---|
| 124 | def __init__(self, blurb, **kwargs): |
|---|
| 125 | super(Blurb, self).__init__(blurb=blurb, **kwargs) |
|---|
| 126 | |
|---|
| 127 | def __repr__(self): |
|---|
| 128 | return 'Blurb(%r, %r)' % (self.position, self.blurb) |
|---|
| 129 | |
|---|
| 130 | setup_all(True) |
|---|
| 131 | |
|---|
| 132 | user = User(blurbs=[Blurb(u'zero'), Blurb(u'one'), Blurb(u'two')]) |
|---|
| 133 | |
|---|
| 134 | session.commit() |
|---|
| 135 | session.clear() |
|---|
| 136 | |
|---|
| 137 | user = User.get(1) |
|---|
| 138 | assert len(user.two_blurbs) == 2 |
|---|
| 139 | assert user.two_blurbs[0].blurb == 'zero' |
|---|
| 140 | assert user.two_blurbs[1].blurb == 'one' |
|---|
| 141 | |
|---|
| 142 | def test_filtered(self): |
|---|
| 143 | class User(Entity): |
|---|
| 144 | two_blurbs = OneToMany('Blurb', filter=lambda c: c.position < 2) |
|---|
| 145 | blurbs = OneToMany('Blurb', |
|---|
| 146 | collection_class=ordering_list('position'), |
|---|
| 147 | order_by='position') |
|---|
| 148 | |
|---|
| 149 | class Blurb(Entity): |
|---|
| 150 | user = ManyToOne('User') |
|---|
| 151 | position = Field(Integer) |
|---|
| 152 | blurb = Field(Unicode(255)) |
|---|
| 153 | |
|---|
| 154 | def __init__(self, blurb, **kwargs): |
|---|
| 155 | super(Blurb, self).__init__(blurb=blurb, **kwargs) |
|---|
| 156 | |
|---|
| 157 | def __repr__(self): |
|---|
| 158 | return 'Blurb(%r, %r)' % (self.position, self.blurb) |
|---|
| 159 | |
|---|
| 160 | setup_all(True) |
|---|
| 161 | |
|---|
| 162 | user = User(blurbs=[Blurb(u'zero'), Blurb(u'one'), Blurb(u'two')]) |
|---|
| 163 | |
|---|
| 164 | session.commit() |
|---|
| 165 | session.clear() |
|---|
| 166 | |
|---|
| 167 | user = User.get(1) |
|---|
| 168 | assert len(user.two_blurbs) == 2 |
|---|
| 169 | assert user.two_blurbs[0].blurb == 'zero' |
|---|
| 170 | assert user.two_blurbs[1].blurb == 'one' |
|---|
| 171 | |
|---|
| 172 | def test_has_many_syntax(self): |
|---|
| 173 | class Person(Entity): |
|---|
| 174 | has_field('name', String(30)) |
|---|
| 175 | has_many('pets', of_kind='Animal') |
|---|
| 176 | |
|---|
| 177 | class Animal(Entity): |
|---|
| 178 | has_field('name', String(30)) |
|---|
| 179 | belongs_to('owner', of_kind='Person') |
|---|
| 180 | |
|---|
| 181 | setup_all(True) |
|---|
| 182 | |
|---|
| 183 | santa = Person(name="Santa Claus") |
|---|
| 184 | rudolph = Animal(name="Rudolph", owner=santa) |
|---|
| 185 | |
|---|
| 186 | session.commit() |
|---|
| 187 | session.clear() |
|---|
| 188 | |
|---|
| 189 | santa = Person.get_by(name="Santa Claus") |
|---|
| 190 | |
|---|
| 191 | assert Animal.get_by(name="Rudolph") in santa.pets |
|---|