1
0
mirror of https://github.com/django/django.git synced 2025-10-27 07:36:08 +00:00

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.
This commit is contained in:
Simon Charette
2025-05-06 13:57:20 -04:00
committed by Sarah Boyce
parent 0b2ed4f7c8
commit e03e5c751c
5 changed files with 42 additions and 3 deletions

View File

@@ -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

View File

@@ -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: