summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDevilsAutumn <bhuvnesh875@gmail.com>2022-11-22 15:04:55 +0530
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-11-22 14:47:21 +0100
commit4035bab56f2862a25cd7bfba41a84e58672cb1cc (patch)
tree7bcf12adc5f6d48b6f9e687d431029e47667105d
parent7d5329852f19c6ae78c6f6f3d3e41835377bf295 (diff)
Fixed #34171 -- Fixed QuerySet.bulk_create() on fields with db_column in unique_fields/update_fields.
Bug in 0f6946495a8ec955b471ca1baaf408ceb53d4796. Thanks Joshua Brooks for the report.
-rw-r--r--django/db/models/query.py9
-rw-r--r--django/db/models/sql/compiler.py4
-rw-r--r--docs/releases/4.1.4.txt3
-rw-r--r--tests/bulk_create/models.py5
-rw-r--r--tests/bulk_create/tests.py32
5 files changed, 46 insertions, 7 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index be8580f2c4..cf419cb8cf 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -720,7 +720,6 @@ class QuerySet(AltersData):
"Unique fields that can trigger the upsert must be provided."
)
# Updating primary keys and non-concrete fields is forbidden.
- update_fields = [self.model._meta.get_field(name) for name in update_fields]
if any(not f.concrete or f.many_to_many for f in update_fields):
raise ValueError(
"bulk_create() can only be used with concrete fields in "
@@ -732,9 +731,6 @@ class QuerySet(AltersData):
"update_fields."
)
if unique_fields:
- unique_fields = [
- self.model._meta.get_field(name) for name in unique_fields
- ]
if any(not f.concrete or f.many_to_many for f in unique_fields):
raise ValueError(
"bulk_create() can only be used with concrete fields "
@@ -786,8 +782,11 @@ class QuerySet(AltersData):
if unique_fields:
# Primary key is allowed in unique_fields.
unique_fields = [
- opts.pk.name if name == "pk" else name for name in unique_fields
+ self.model._meta.get_field(opts.pk.name if name == "pk" else name)
+ for name in unique_fields
]
+ if update_fields:
+ update_fields = [self.model._meta.get_field(name) for name in update_fields]
on_conflict = self._check_bulk_create_options(
ignore_conflicts,
update_conflicts,
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 0562a71dd1..caf36382b5 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -1725,8 +1725,8 @@ class SQLInsertCompiler(SQLCompiler):
on_conflict_suffix_sql = self.connection.ops.on_conflict_suffix_sql(
fields,
self.query.on_conflict,
- self.query.update_fields,
- self.query.unique_fields,
+ (f.column for f in self.query.update_fields),
+ (f.column for f in self.query.unique_fields),
)
if (
self.returning_fields
diff --git a/docs/releases/4.1.4.txt b/docs/releases/4.1.4.txt
index 7cdd2521ea..509135f3b2 100644
--- a/docs/releases/4.1.4.txt
+++ b/docs/releases/4.1.4.txt
@@ -23,3 +23,6 @@ Bugfixes
* Fixed a bug in Django 4.1 that caused a crash of ``QuerySet.bulk_create()``
with ``"pk"`` in ``unique_fields`` (:ticket:`34177`).
+
+* Fixed a bug in Django 4.1 that caused a crash of ``QuerySet.bulk_create()``
+ on fields with ``db_column`` (:ticket:`34171`).
diff --git a/tests/bulk_create/models.py b/tests/bulk_create/models.py
index 27abc416bd..8a21c7dfa1 100644
--- a/tests/bulk_create/models.py
+++ b/tests/bulk_create/models.py
@@ -69,6 +69,11 @@ class TwoFields(models.Model):
name = models.CharField(max_length=15, null=True)
+class FieldsWithDbColumns(models.Model):
+ rank = models.IntegerField(unique=True, db_column="rAnK")
+ name = models.CharField(max_length=15, null=True, db_column="oTheRNaMe")
+
+
class UpsertConflict(models.Model):
number = models.IntegerField(unique=True)
rank = models.IntegerField()
diff --git a/tests/bulk_create/tests.py b/tests/bulk_create/tests.py
index 6c490d1235..a5050c9b0b 100644
--- a/tests/bulk_create/tests.py
+++ b/tests/bulk_create/tests.py
@@ -21,6 +21,7 @@ from django.test import (
from .models import (
BigAutoFieldModel,
Country,
+ FieldsWithDbColumns,
NoFields,
NullableFields,
Pizzeria,
@@ -772,3 +773,34 @@ class BulkCreateTests(TestCase):
@skipIfDBFeature("supports_update_conflicts_with_target")
def test_update_conflicts_no_unique_fields(self):
self._test_update_conflicts([])
+
+ @skipUnlessDBFeature(
+ "supports_update_conflicts", "supports_update_conflicts_with_target"
+ )
+ def test_update_conflicts_unique_fields_update_fields_db_column(self):
+ FieldsWithDbColumns.objects.bulk_create(
+ [
+ FieldsWithDbColumns(rank=1, name="a"),
+ FieldsWithDbColumns(rank=2, name="b"),
+ ]
+ )
+ self.assertEqual(FieldsWithDbColumns.objects.count(), 2)
+
+ conflicting_objects = [
+ FieldsWithDbColumns(rank=1, name="c"),
+ FieldsWithDbColumns(rank=2, name="d"),
+ ]
+ FieldsWithDbColumns.objects.bulk_create(
+ conflicting_objects,
+ update_conflicts=True,
+ unique_fields=["rank"],
+ update_fields=["name"],
+ )
+ self.assertEqual(FieldsWithDbColumns.objects.count(), 2)
+ self.assertCountEqual(
+ FieldsWithDbColumns.objects.values("rank", "name"),
+ [
+ {"rank": 1, "name": "c"},
+ {"rank": 2, "name": "d"},
+ ],
+ )