[1.10.x] Fixed #27385 -- Fixed QuerySet.bulk_create() on PostgreSQL when the number of objects is a multiple plus one of batch_size.

Backport of b3bd3aa07c from master
This commit is contained in:
David Barragán Merino 2016-10-25 16:51:45 +02:00 committed by Tim Graham
parent 3ca9df26ba
commit 736f7e7ed7
3 changed files with 16 additions and 6 deletions

View File

@ -1060,9 +1060,9 @@ class QuerySet(object):
for item in [objs[i:i + batch_size] for i in range(0, len(objs), batch_size)]: for item in [objs[i:i + batch_size] for i in range(0, len(objs), batch_size)]:
if connections[self.db].features.can_return_ids_from_bulk_insert: if connections[self.db].features.can_return_ids_from_bulk_insert:
inserted_id = self._insert(item, fields=fields, using=self.db, return_id=True) inserted_id = self._insert(item, fields=fields, using=self.db, return_id=True)
if len(objs) > 1: if isinstance(inserted_id, list):
inserted_ids.extend(inserted_id) inserted_ids.extend(inserted_id)
if len(objs) == 1: else:
inserted_ids.append(inserted_id) inserted_ids.append(inserted_id)
else: else:
self._insert(item, fields=fields, using=self.db) self._insert(item, fields=fields, using=self.db)

View File

@ -20,3 +20,6 @@ Bugfixes
* Made the ``JavaScriptCatalog`` view respect the ``packages`` argument; * Made the ``JavaScriptCatalog`` view respect the ``packages`` argument;
previously it was ignored (:ticket:`27374`). previously it was ignored (:ticket:`27374`).
* Fixed ``QuerySet.bulk_create()`` on PostgreSQL when the number of objects is
a multiple plus one of ``batch_size`` (:ticket:`27385`).

View File

@ -171,11 +171,18 @@ class BulkCreateTests(TestCase):
def test_explicit_batch_size(self): def test_explicit_batch_size(self):
objs = [TwoFields(f1=i, f2=i) for i in range(0, 4)] objs = [TwoFields(f1=i, f2=i) for i in range(0, 4)]
TwoFields.objects.bulk_create(objs, 2) num_objs = len(objs)
self.assertEqual(TwoFields.objects.count(), len(objs)) TwoFields.objects.bulk_create(objs, batch_size=1)
self.assertEqual(TwoFields.objects.count(), num_objs)
TwoFields.objects.all().delete() TwoFields.objects.all().delete()
TwoFields.objects.bulk_create(objs, len(objs)) TwoFields.objects.bulk_create(objs, batch_size=2)
self.assertEqual(TwoFields.objects.count(), len(objs)) self.assertEqual(TwoFields.objects.count(), num_objs)
TwoFields.objects.all().delete()
TwoFields.objects.bulk_create(objs, batch_size=3)
self.assertEqual(TwoFields.objects.count(), num_objs)
TwoFields.objects.all().delete()
TwoFields.objects.bulk_create(objs, batch_size=num_objs)
self.assertEqual(TwoFields.objects.count(), num_objs)
def test_empty_model(self): def test_empty_model(self):
NoFields.objects.bulk_create([NoFields() for i in range(2)]) NoFields.objects.bulk_create([NoFields() for i in range(2)])