﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
37238	6.1: save() falls back to python default for primary key that should come from related instance instead	Jacob Walls	Jacob Walls	"When saving an object whose primary key is a `OneToOneField`, and when that value is meant to come from an unsaved related object, and when that related object uses `db_default`, a2348c85fc6c20087935c74cd99340dd4ef2dcdc has the unintentional effect of falling back to the field's `default` instead of getting it from the related object once saved. EDIT: before 6.1, the fallback was to the related object's db_default expression, which isn't quite right either, so my current proposal is to just match the 6.0 behavior and then bounce the rest to a follow-up issue.

To demonstrate, adjust a test being drafted in this [https://github.com/django/django/pull/21677 other PR] (where the `bulk_create()` case was considered and handled) to use `save()` instead:

Passes before a2348c85fc6c20087935c74cd99340dd4ef2dcdc on SQLite. Other databases have other behaviors, like raising integrity errors, so we might need some test skips here. This should be rewritten to use Now() instead of a constant value; I found the constant value was easier to debug.

{{{#!diff
diff --git a/tests/bulk_create/models.py b/tests/bulk_create/models.py
index bc9beba990..34ea0bf3f8 100644
--- a/tests/bulk_create/models.py
+++ b/tests/bulk_create/models.py
@@ -157,3 +157,22 @@ class DbDefaultPrimaryKey(models.Model):
 
     class Meta:
         required_db_features = {""supports_expression_defaults""}
+
+
+class IntegerDbDefaultPrimaryKey(models.Model):
+    id = models.IntegerField(primary_key=True, db_default=42)
+
+    class Meta:
+        required_db_features = {""supports_expression_defaults""}
+
+
+class RelatedToDbDefaultPrimaryKey(models.Model):
+    related = models.OneToOneField(
+        IntegerDbDefaultPrimaryKey,
+        on_delete=models.CASCADE,
+        primary_key=True,
+        default=1,
+    )
+
+    class Meta:
+        required_db_features = {""supports_expression_defaults""}
diff --git a/tests/bulk_create/tests.py b/tests/bulk_create/tests.py
index 397fcb9186..2692d62fb1 100644
--- a/tests/bulk_create/tests.py
+++ b/tests/bulk_create/tests.py
@@ -27,6 +27,7 @@ from .models import (
     DbDefaultModel,
     DbDefaultPrimaryKey,
     FieldsWithDbColumns,
+    IntegerDbDefaultPrimaryKey,
     NoFields,
     NullableFields,
     Pizzeria,
@@ -35,6 +36,7 @@ from .models import (
     ProxyMultiProxyCountry,
     ProxyProxyCountry,
     RelatedModel,
+    RelatedToDbDefaultPrimaryKey,
     Restaurant,
     SmallAutoFieldModel,
     State,
@@ -439,6 +441,19 @@ class BulkCreateTests(TestCase):
         child = NullableFields.objects.get(integer_field=88)
         self.assertEqual(child.auto_field, parent)
 
+    @skipUnlessDBFeature(
+        ""can_return_columns_from_insert"", ""supports_expression_defaults""
+    )
+    def test_pk_from_related_instance_saved_after_init_with_defaults(self):
+        # Ensure that the related field's Python default references a
+        # different valid object.
+        IntegerDbDefaultPrimaryKey.objects.create(pk=1)
+        related_object = IntegerDbDefaultPrimaryKey()
+        obj = RelatedToDbDefaultPrimaryKey(related=related_object)
+        related_object.save()
+        obj.save()
+        self.assertEqual(obj.pk, related_object.pk)
+
     def test_unsaved_parent(self):
         parent = NoFields()
         msg = (
}}}

{{{#!py
======================================================================
FAIL: test_pk_from_related_instance_saved_after_init_with_defaults (bulk_create.tests.BulkCreateTests.test_pk_from_related_instance_saved_after_init_with_defaults)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ""/Users/jwalls/django/tests/bulk_create/tests.py"", line 455, in test_pk_from_related_instance_saved_after_init_with_defaults
    self.assertEqual(obj.pk, related_object.pk)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 1 != 42

----------------------------------------------------------------------
Ran 1 test in 0.007s

FAILED (failures=1)
}}}"	Bug	assigned	Database layer (models, ORM)	6.1	Release blocker			Mariusz Felisiak	Unreviewed	0	0	0	0	0	0
