summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2025-05-06 13:57:20 -0400
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-05-16 08:13:57 +0200
commite03e5c751c56db5f4cb99e142c92d7d8db3a5463 (patch)
tree474e4baf6ac38c2e940552a167bc8562eae142b3 /django/db
parent0b2ed4f7c8396c8d9aa8428a40e6b25c31312889 (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 'django/db')
-rw-r--r--django/db/models/base.py1
-rw-r--r--django/db/models/query_utils.py5
2 files changed, 4 insertions, 2 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 72ba0471a4..d4559e0693 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -859,6 +859,7 @@ class Model(AltersData, metaclass=ModelBase):
not force_insert
and deferred_non_generated_fields
and using == self._state.db
+ and self._is_pk_set()
):
field_names = set()
pk_fields = self._meta.pk_fields
diff --git a/django/db/models/query_utils.py b/django/db/models/query_utils.py
index f0ae810f47..3e644a3c26 100644
--- a/django/db/models/query_utils.py
+++ b/django/db/models/query_utils.py
@@ -220,9 +220,10 @@ class DeferredAttribute:
# might be able to reuse the already loaded value. Refs #18343.
val = self._check_parent_chain(instance)
if val is None:
- if not instance._is_pk_set() and self.field.generated:
+ if not instance._is_pk_set():
raise AttributeError(
- "Cannot read a generated field from an unsaved model."
+ f"Cannot retrieve deferred field {field_name!r} "
+ "from an unsaved model."
)
instance.refresh_from_db(fields=[field_name])
else: