Opened 50 minutes ago
Last modified 19 minutes ago
#37238 assigned Bug
6.1: save() falls back to python default for primary key that should come from related instance instead
| Reported by: | Jacob Walls | Owned by: | Jacob Walls |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 6.1 |
| Severity: | Release blocker | Keywords: | |
| Cc: | Mariusz Felisiak | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
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.
To demonstrate, adjust a test being drafted in this 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.
-
tests/bulk_create/models.py
diff --git a/tests/bulk_create/models.py b/tests/bulk_create/models.py index bc9beba990..34ea0bf3f8 100644
a b class DbDefaultPrimaryKey(models.Model): 157 157 158 158 class Meta: 159 159 required_db_features = {"supports_expression_defaults"} 160 161 162 class IntegerDbDefaultPrimaryKey(models.Model): 163 id = models.IntegerField(primary_key=True, db_default=42) 164 165 class Meta: 166 required_db_features = {"supports_expression_defaults"} 167 168 169 class RelatedToDbDefaultPrimaryKey(models.Model): 170 related = models.OneToOneField( 171 IntegerDbDefaultPrimaryKey, 172 on_delete=models.CASCADE, 173 primary_key=True, 174 default=1, 175 ) 176 177 class Meta: 178 required_db_features = {"supports_expression_defaults"} -
tests/bulk_create/tests.py
diff --git a/tests/bulk_create/tests.py b/tests/bulk_create/tests.py index 397fcb9186..2692d62fb1 100644
a b from .models import ( 27 27 DbDefaultModel, 28 28 DbDefaultPrimaryKey, 29 29 FieldsWithDbColumns, 30 IntegerDbDefaultPrimaryKey, 30 31 NoFields, 31 32 NullableFields, 32 33 Pizzeria, … … from .models import ( 35 36 ProxyMultiProxyCountry, 36 37 ProxyProxyCountry, 37 38 RelatedModel, 39 RelatedToDbDefaultPrimaryKey, 38 40 Restaurant, 39 41 SmallAutoFieldModel, 40 42 State, … … class BulkCreateTests(TestCase): 439 441 child = NullableFields.objects.get(integer_field=88) 440 442 self.assertEqual(child.auto_field, parent) 441 443 444 @skipUnlessDBFeature( 445 "can_return_columns_from_insert", "supports_expression_defaults" 446 ) 447 def test_pk_from_related_instance_saved_after_init_with_defaults(self): 448 # Ensure that the related field's Python default references a 449 # different valid object. 450 IntegerDbDefaultPrimaryKey.objects.create(pk=1) 451 related_object = IntegerDbDefaultPrimaryKey() 452 obj = RelatedToDbDefaultPrimaryKey(related=related_object) 453 related_object.save() 454 obj.save() 455 self.assertEqual(obj.pk, related_object.pk) 456 442 457 def test_unsaved_parent(self): 443 458 parent = NoFields() 444 459 msg = (
====================================================================== 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)
Change History (1)
comment:1 by , 19 minutes ago
| Description: | modified (diff) |
|---|---|
| Summary: | 6.1: save() falls back to db_default for primary key that should come from related instance instead → 6.1: save() falls back to python default for primary key that should come from related instance instead |