Author: adrian
Date: 2011-12-09 15:16:56 -0800 (Fri, 09 Dec 2011)
New Revision: 17189

Modified:
   django/trunk/django/db/models/query.py
   django/trunk/tests/regressiontests/transactions_regress/models.py
   django/trunk/tests/regressiontests/transactions_regress/tests.py
Log:
Fixed #16818 -- Fixed ORM bug with many-to-many add() method where it wasn't 
committing the change. Thanks, pressureman and kmtracey

Modified: django/trunk/django/db/models/query.py
===================================================================
--- django/trunk/django/db/models/query.py      2011-12-09 23:14:04 UTC (rev 
17188)
+++ django/trunk/django/db/models/query.py      2011-12-09 23:16:56 UTC (rev 
17189)
@@ -396,18 +396,29 @@
         self._for_write = True
         connection = connections[self.db]
         fields = self.model._meta.local_fields
-        if 
(connection.features.can_combine_inserts_with_and_without_auto_increment_pk
-            and self.model._meta.has_auto_field):
-            self.model._base_manager._insert(objs, fields=fields, 
using=self.db)
+        if not transaction.is_managed(using=self.db):
+            transaction.enter_transaction_management(using=self.db)
+            forced_managed = True
         else:
-            objs_with_pk, objs_without_pk = partition(
-                lambda o: o.pk is None,
-                objs
-            )
-            if objs_with_pk:
-                self.model._base_manager._insert(objs_with_pk, fields=fields, 
using=self.db)
-            if objs_without_pk:
-                self.model._base_manager._insert(objs_without_pk, fields=[f 
for f in fields if not isinstance(f, AutoField)], using=self.db)
+            forced_managed = False
+        try:
+            if 
(connection.features.can_combine_inserts_with_and_without_auto_increment_pk
+                and self.model._meta.has_auto_field):
+                self.model._base_manager._insert(objs, fields=fields, 
using=self.db)
+            else:
+                objs_with_pk, objs_without_pk = partition(lambda o: o.pk is 
None, objs)
+                if objs_with_pk:
+                    self.model._base_manager._insert(objs_with_pk, 
fields=fields, using=self.db)
+                if objs_without_pk:
+                    self.model._base_manager._insert(objs_without_pk, 
fields=[f for f in fields if not isinstance(f, AutoField)], using=self.db)
+            if forced_managed:
+                transaction.commit(using=self.db)
+            else:
+                transaction.commit_unless_managed(using=self.db)
+        finally:
+            if forced_managed:
+                transaction.leave_transaction_management(using=self.db)
+
         return objs
 
     def get_or_create(self, **kwargs):

Modified: django/trunk/tests/regressiontests/transactions_regress/models.py
===================================================================
--- django/trunk/tests/regressiontests/transactions_regress/models.py   
2011-12-09 23:14:04 UTC (rev 17188)
+++ django/trunk/tests/regressiontests/transactions_regress/models.py   
2011-12-09 23:16:56 UTC (rev 17189)
@@ -2,3 +2,9 @@
 
 class Mod(models.Model):
     fld = models.IntegerField()
+
+class M2mA(models.Model):
+    others = models.ManyToManyField('M2mB')
+
+class M2mB(models.Model):
+    fld = models.IntegerField()

Modified: django/trunk/tests/regressiontests/transactions_regress/tests.py
===================================================================
--- django/trunk/tests/regressiontests/transactions_regress/tests.py    
2011-12-09 23:14:04 UTC (rev 17188)
+++ django/trunk/tests/regressiontests/transactions_regress/tests.py    
2011-12-09 23:16:56 UTC (rev 17189)
@@ -5,7 +5,7 @@
 from django.db.transaction import commit_on_success, commit_manually, 
TransactionManagementError
 from django.test import TransactionTestCase, skipUnlessDBFeature
 
-from .models import Mod
+from .models import Mod, M2mA, M2mB
 
 
 class TestTransactionClosing(TransactionTestCase):
@@ -164,3 +164,17 @@
             _ = User.objects.all()[0]
         except:
             self.fail("A transaction consisting of a failed operation was not 
closed.")
+
+class TestManyToManyAddTransaction(TransactionTestCase):
+    def test_manyrelated_add_commit(self):
+        "Test for https://code.djangoproject.com/ticket/16818";
+        a = M2mA.objects.create()
+        b = M2mB.objects.create(fld=10)
+        a.others.add(b)
+
+        # We're in a TransactionTestCase and have not changed transaction
+        # behavior from default of "autocommit", so this rollback should not
+        # actually do anything. If it does in fact undo our add, that's a bug
+        # that the bulk insert was not auto-committed.
+        transaction.rollback()
+        self.assertEqual(a.others.count(), 1)

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to