Commit 073d987a authored by Adrian Holovaty's avatar Adrian Holovaty
Browse files

Fixed #16818 -- Fixed ORM bug with many-to-many add() method where it wasn't...

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
parent 594a45ed
Loading
Loading
Loading
Loading
+22 −11
Original line number Diff line number Diff line
@@ -396,18 +396,29 @@ class QuerySet(object):
        self._for_write = True
        connection = connections[self.db]
        fields = self.model._meta.local_fields
        if not transaction.is_managed(using=self.db):
            transaction.enter_transaction_management(using=self.db)
            forced_managed = True
        else:
            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
            )
                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):
+6 −0
Original line number Diff line number Diff line
@@ -2,3 +2,9 @@ from django.db import models

class Mod(models.Model):
    fld = models.IntegerField()

class M2mA(models.Model):
    others = models.ManyToManyField('M2mB')

class M2mB(models.Model):
    fld = models.IntegerField()
+15 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ from django.db import connection, transaction
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 @@ class TestTransactionClosing(TransactionTestCase):
            _ = 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)