diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 0d5cd764da..6f90f11f1b 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -8,7 +8,7 @@ from django.core.exceptions import EmptyResultSet, FieldError, FullResultSet from django.db import DatabaseError, NotSupportedError from django.db.models.constants import LOOKUP_SEP from django.db.models.expressions import ColPairs, F, OrderBy, RawSQL, Ref, Value -from django.db.models.fields import composite +from django.db.models.fields import AutoField, composite from django.db.models.functions import Cast, Random from django.db.models.lookups import Lookup from django.db.models.query_utils import select_related_descend @@ -1910,17 +1910,23 @@ class SQLInsertCompiler(SQLCompiler): ) ] cols = [field.get_col(opts.db_table) for field in self.returning_fields] - else: - cols = [opts.pk.get_col(opts.db_table)] + elif returning_fields and isinstance( + returning_field := returning_fields[0], AutoField + ): + cols = [returning_field.get_col(opts.db_table)] rows = [ ( self.connection.ops.last_insert_id( cursor, opts.db_table, - opts.pk.column, + returning_field.column, ), ) ] + else: + # Backend doesn't support returning fields and no auto-field + # that can be retrieved from `last_insert_id` was specified. + return [] converters = self.get_converters(cols) if converters: rows = self.apply_converters(rows, converters) diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py index 599efafe7e..fdea06b23d 100644 --- a/tests/model_fields/models.py +++ b/tests/model_fields/models.py @@ -527,6 +527,19 @@ class GeneratedModel(models.Model): required_db_features = {"supports_stored_generated_columns"} +class GeneratedModelNonAutoPk(models.Model): + id = models.IntegerField(primary_key=True) + a = models.IntegerField() + b = models.GeneratedField( + expression=F("a"), + output_field=models.IntegerField(), + db_persist=True, + ) + + class Meta: + required_db_features = {"supports_stored_generated_columns"} + + class GeneratedModelVirtual(models.Model): a = models.IntegerField() b = models.IntegerField() diff --git a/tests/model_fields/test_generatedfield.py b/tests/model_fields/test_generatedfield.py index c185e19d8b..e00a665ec8 100644 --- a/tests/model_fields/test_generatedfield.py +++ b/tests/model_fields/test_generatedfield.py @@ -22,6 +22,7 @@ from .models import ( GeneratedModelCheckConstraint, GeneratedModelCheckConstraintVirtual, GeneratedModelFieldWithConverters, + GeneratedModelNonAutoPk, GeneratedModelNull, GeneratedModelNullVirtual, GeneratedModelOutputFieldDbCollation, @@ -356,6 +357,12 @@ class StoredGeneratedFieldTests(GeneratedFieldTestMixin, TestCase): obj = self._refresh_if_needed(obj) self.assertEqual(obj.field, obj.field_copy) + def test_create_with_non_auto_pk(self): + obj = GeneratedModelNonAutoPk.objects.create(id=1, a=2) + self.assertEqual(obj.id, 1) + self.assertEqual(obj.a, 2) + self.assertEqual(obj.b, 2) + @skipUnlessDBFeature("supports_virtual_generated_columns") class VirtualGeneratedFieldTests(GeneratedFieldTestMixin, TestCase):