Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
@adrianholovaty adrianholovaty authored
View
33 django/db/models/query.py
@@ -396,18 +396,29 @@ def bulk_create(self, objs):
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):
View
6 tests/regressiontests/transactions_regress/models.py
@@ -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()
View
16 tests/regressiontests/transactions_regress/tests.py
@@ -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 @@ def create_system_user():
_ = 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)

0 comments on commit 073d987

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