diff options
| author | Simon Charette <charette.s@gmail.com> | 2025-05-06 13:57:20 -0400 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-05-16 08:13:57 +0200 |
| commit | e03e5c751c56db5f4cb99e142c92d7d8db3a5463 (patch) | |
| tree | 474e4baf6ac38c2e940552a167bc8562eae142b3 /tests | |
| parent | 0b2ed4f7c8396c8d9aa8428a40e6b25c31312889 (diff) | |
Fixed #33312 -- Raised explicit exception when copying deferred model instances.
Previously save() would crash with an attempted forced update message, and both
save(force_insert=True) and bulk_create() would crash with DoesNotExist errors
trying to retrieve rows with an empty primary key (id IS NULL).
Implementing deferred field model instance copying might be doable in certain
cases (e.g. when all the deferred fields are db generated) but that's not
trivial to implement in a backward compatible way.
Thanks Adam Sołtysik for the report and test and Clifford for the review.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/defer_regress/tests.py | 22 | ||||
| -rw-r--r-- | tests/model_fields/test_generatedfield.py | 2 |
2 files changed, 23 insertions, 1 deletions
diff --git a/tests/defer_regress/tests.py b/tests/defer_regress/tests.py index 1209325f21..c45a503630 100644 --- a/tests/defer_regress/tests.py +++ b/tests/defer_regress/tests.py @@ -366,3 +366,25 @@ class DeferDeletionSignalsTests(TestCase): Proxy.objects.only("value").get(pk=self.item_pk).delete() self.assertEqual(self.pre_delete_senders, [Proxy]) self.assertEqual(self.post_delete_senders, [Proxy]) + + +class DeferCopyInstanceTests(TestCase): + @classmethod + def setUpTestData(cls): + SimpleItem.objects.create(name="test", value=42) + cls.deferred_item = SimpleItem.objects.defer("value").first() + cls.deferred_item.pk = None + cls.deferred_item._state.adding = True + cls.expected_msg = ( + "Cannot retrieve deferred field 'value' from an unsaved model." + ) + + def test_save(self): + with self.assertRaisesMessage(AttributeError, self.expected_msg): + self.deferred_item.save(force_insert=True) + with self.assertRaisesMessage(AttributeError, self.expected_msg): + self.deferred_item.save() + + def test_bulk_create(self): + with self.assertRaisesMessage(AttributeError, self.expected_msg): + SimpleItem.objects.bulk_create([self.deferred_item]) diff --git a/tests/model_fields/test_generatedfield.py b/tests/model_fields/test_generatedfield.py index 9bc96a86bb..b6a933451d 100644 --- a/tests/model_fields/test_generatedfield.py +++ b/tests/model_fields/test_generatedfield.py @@ -180,7 +180,7 @@ class GeneratedFieldTestMixin: def test_unsaved_error(self): m = self.base_model(a=1, b=2) - msg = "Cannot read a generated field from an unsaved model." + msg = "Cannot retrieve deferred field 'field' from an unsaved model." with self.assertRaisesMessage(AttributeError, msg): m.field |
