Commits

Mike Bayer  committed e8b2637

- backref remove object operation doesn't fail if the other-side
collection doesn't contain the item, supports noload collections
[ticket:813]

  • Participants
  • Parent commits 52353e0

Comments (0)

Files changed (3)

 - Added partial index support for PostgreSQL. Use the postgres_where keyword
   on the Index.
 
+- backref remove object operation doesn't fail if the other-side
+  collection doesn't contain the item, supports noload collections
+  [ticket:813]
+
 - The IdentifierPreprarer's _requires_quotes test is now regex based.  Any
   out-of-tree dialects that provide custom sets of legal_characters or
   illegal_initial_characters will need to move to regexes or override

File lib/sqlalchemy/orm/attributes.py

         if oldchild is child:
             return
         if oldchild is not None:
-            getattr(oldchild.__class__, self.key).impl.remove(oldchild._state, obj, initiator)
+            # With lazy=None, there's no guarantee that the full collection is
+            # present when updating via a backref.
+            impl = getattr(oldchild.__class__, self.key).impl
+            try:                
+                impl.remove(oldchild._state, obj, initiator)
+            except (ValueError, KeyError, IndexError):
+                pass
         if child is not None:
             getattr(child.__class__, self.key).impl.append(child._state, obj, initiator)
 

File test/orm/unitofwork.py

         u1 = Session.query(User).get(u1.user_id)
         u2 = Session.query(User).get(u2.user_id)
         assert a1.user is u2
+
+    def test_bidirectional_noload(self):
+        mapper(User, users, properties={
+            'addresses':relation(Address, backref='user', lazy=None)
+        })
+        mapper(Address, addresses)
+
+        sess = Session()
+
+        # try it on unsaved objects
+        u1 = User()
+        a1 = Address()
+        a1.user = u1
+        sess.save(u1)
+        sess.flush()
+        sess.clear()
+
+        a1 = sess.query(Address).get(a1.address_id)
+
+        a1.user = None
+        sess.flush()
+        sess.clear()
+        assert sess.query(Address).get(a1.address_id).user is None
+        assert sess.query(User).get(u1.user_id).addresses == []
+
         
 class ManyToManyTest(ORMTest):
     metadata = tables.metadata