Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #16818 -- Fixed ORM bug with many-to-many add() method where it…

… wasn't committing the change. Thanks, pressureman and kmtracey

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17189 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 073d987a84d7ebdf3b70789f22b8a12a9f5ae96f 1 parent 594a45e
Adrian Holovaty authored December 09, 2011
33  django/db/models/query.py
@@ -396,18 +396,29 @@ def bulk_create(self, objs):
396 396
         self._for_write = True
397 397
         connection = connections[self.db]
398 398
         fields = self.model._meta.local_fields
399  
-        if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
400  
-            and self.model._meta.has_auto_field):
401  
-            self.model._base_manager._insert(objs, fields=fields, using=self.db)
  399
+        if not transaction.is_managed(using=self.db):
  400
+            transaction.enter_transaction_management(using=self.db)
  401
+            forced_managed = True
402 402
         else:
403  
-            objs_with_pk, objs_without_pk = partition(
404  
-                lambda o: o.pk is None,
405  
-                objs
406  
-            )
407  
-            if objs_with_pk:
408  
-                self.model._base_manager._insert(objs_with_pk, fields=fields, using=self.db)
409  
-            if objs_without_pk:
410  
-                self.model._base_manager._insert(objs_without_pk, fields=[f for f in fields if not isinstance(f, AutoField)], using=self.db)
  403
+            forced_managed = False
  404
+        try:
  405
+            if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
  406
+                and self.model._meta.has_auto_field):
  407
+                self.model._base_manager._insert(objs, fields=fields, using=self.db)
  408
+            else:
  409
+                objs_with_pk, objs_without_pk = partition(lambda o: o.pk is None, objs)
  410
+                if objs_with_pk:
  411
+                    self.model._base_manager._insert(objs_with_pk, fields=fields, using=self.db)
  412
+                if objs_without_pk:
  413
+                    self.model._base_manager._insert(objs_without_pk, fields=[f for f in fields if not isinstance(f, AutoField)], using=self.db)
  414
+            if forced_managed:
  415
+                transaction.commit(using=self.db)
  416
+            else:
  417
+                transaction.commit_unless_managed(using=self.db)
  418
+        finally:
  419
+            if forced_managed:
  420
+                transaction.leave_transaction_management(using=self.db)
  421
+
411 422
         return objs
412 423
 
413 424
     def get_or_create(self, **kwargs):
6  tests/regressiontests/transactions_regress/models.py
@@ -2,3 +2,9 @@
2 2
 
3 3
 class Mod(models.Model):
4 4
     fld = models.IntegerField()
  5
+
  6
+class M2mA(models.Model):
  7
+    others = models.ManyToManyField('M2mB')
  8
+
  9
+class M2mB(models.Model):
  10
+    fld = models.IntegerField()
16  tests/regressiontests/transactions_regress/tests.py
@@ -5,7 +5,7 @@
5 5
 from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
6 6
 from django.test import TransactionTestCase, skipUnlessDBFeature
7 7
 
8  
-from .models import Mod
  8
+from .models import Mod, M2mA, M2mB
9 9
 
10 10
 
11 11
 class TestTransactionClosing(TransactionTestCase):
@@ -164,3 +164,17 @@ def create_system_user():
164 164
             _ = User.objects.all()[0]
165 165
         except:
166 166
             self.fail("A transaction consisting of a failed operation was not closed.")
  167
+
  168
+class TestManyToManyAddTransaction(TransactionTestCase):
  169
+    def test_manyrelated_add_commit(self):
  170
+        "Test for https://code.djangoproject.com/ticket/16818"
  171
+        a = M2mA.objects.create()
  172
+        b = M2mB.objects.create(fld=10)
  173
+        a.others.add(b)
  174
+
  175
+        # We're in a TransactionTestCase and have not changed transaction
  176
+        # behavior from default of "autocommit", so this rollback should not
  177
+        # actually do anything. If it does in fact undo our add, that's a bug
  178
+        # that the bulk insert was not auto-committed.
  179
+        transaction.rollback()
  180
+        self.assertEqual(a.others.count(), 1)

0 notes on commit 073d987

Please sign in to comment.
Something went wrong with that request. Please try again.