Ticket #16818: 16818.diff

File 16818.diff, 4.0 KB (added by kmtracey, 3 years ago)

Tentative fix

  • django/db/models/query.py

    diff -r 09437beebc4e django/db/models/query.py
    a b  
    394394        self._for_write = True
    395395        connection = connections[self.db]
    396396        fields = self.model._meta.local_fields
    397         if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
    398             and self.model._meta.has_auto_field):
    399             self.model._base_manager._insert(objs, fields=fields, using=self.db)
     397        if not transaction.is_managed(using=self.db):
     398            transaction.enter_transaction_management(using=self.db)
     399            forced_managed = True
    400400        else:
    401             objs_with_pk, objs_without_pk = partition(
    402                 lambda o: o.pk is None,
    403                 objs
    404             )
    405             if objs_with_pk:
    406                 self.model._base_manager._insert(objs_with_pk, fields=fields, using=self.db)
    407             if objs_without_pk:
    408                 self.model._base_manager._insert(objs_without_pk, fields=[f for f in fields if not isinstance(f, AutoField)], using=self.db)
     401            forced_managed = False
     402        try:
     403            if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
     404                and self.model._meta.has_auto_field):
     405                self.model._base_manager._insert(objs, fields=fields, using=self.db)
     406            else:
     407                objs_with_pk, objs_without_pk = partition(
     408                    lambda o: o.pk is None,
     409                    objs
     410                )
     411                if objs_with_pk:
     412                    self.model._base_manager._insert(objs_with_pk, fields=fields, using=self.db)
     413                if objs_without_pk:
     414                    self.model._base_manager._insert(objs_without_pk, fields=[f for f in fields if not isinstance(f, AutoField)], using=self.db)
     415            if forced_managed:
     416                transaction.commit(using=self.db)
     417            else:
     418                transaction.commit_unless_managed(using=self.db)
     419        finally:
     420            if forced_managed:
     421                transaction.leave_transaction_management(using=self.db)
     422
    409423        return objs
    410424
    411425    def get_or_create(self, **kwargs):
  • tests/regressiontests/transactions_regress/models.py

    diff -r 09437beebc4e tests/regressiontests/transactions_regress/models.py
    a b  
    22
    33class Mod(models.Model):
    44    fld = models.IntegerField()
     5
     6class M2mA(models.Model):
     7    others = models.ManyToManyField('M2mB')
     8
     9class M2mB(models.Model):
     10    fld = models.IntegerField()
  • tests/regressiontests/transactions_regress/tests.py

    diff -r 09437beebc4e tests/regressiontests/transactions_regress/tests.py
    a b  
    55from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
    66from django.test import TransactionTestCase, skipUnlessDBFeature
    77
    8 from .models import Mod
     8from .models import Mod, M2mA, M2mB
    99
    1010
    1111class TestTransactionClosing(TransactionTestCase):
     
    164164            _ = User.objects.all()[0]
    165165        except:
    166166            self.fail("A transaction consisting of a failed operation was not closed.")
     167
     168class TestManyToManyAddTransaction(TransactionTestCase):
     169    def test_manyrelated_add_commit(self):
     170        """test for 16818"""
     171        a = M2mA.objects.create()
     172        b = M2mB.objects.create(fld=10)
     173        a.others.add(b)
     174        # We're in a TransactionTestCase and have not changed transaction behavior from
     175        # default of "autocommit", so this rollback should not actually do anything. If it
     176        # does in fact un-do our add, that's a bug that the bulk insert was not auto-committed.
     177        transaction.rollback()
     178        self.assertQuerysetEqual(a.others.all(),['<M2mB: M2mB object>'])
Back to Top