diff options
| author | Simon Charette <charette.s@gmail.com> | 2025-03-19 01:39:19 -0400 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2025-09-14 00:27:50 +0200 |
| commit | 94680437a45a71c70ca8bd2e68b72aa1e2eff337 (patch) | |
| tree | 0246e0b5a8dde81f0a327e1c7c7e3accd9257870 /django/db | |
| parent | 55a0073b3beb9de8f7c1f7c44a7d0bc10126c841 (diff) | |
Fixed #27222 -- Refreshed model field values assigned expressions on save().
Removed the can_return_columns_from_insert skip gates on existing
field_defaults tests to confirm the expected number of queries are
performed and that returning field overrides are respected.
Diffstat (limited to 'django/db')
| -rw-r--r-- | django/db/models/base.py | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py index 93e53bde95..518cfc44a2 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -1102,6 +1102,11 @@ class Model(AltersData, metaclass=ModelBase): and f.referenced_fields.intersection(non_pks_non_generated) ) ] + for field, _model, value in values: + if (update_fields is None or field.name in update_fields) and hasattr( + value, "resolve_expression" + ): + returning_fields.append(field) results = self._do_update( base_qs, using, @@ -1142,7 +1147,15 @@ class Model(AltersData, metaclass=ModelBase): for f in meta.local_concrete_fields if not f.generated and (pk_set or f is not meta.auto_field) ] - returning_fields = meta.db_returning_fields + returning_fields = list(meta.db_returning_fields) + for field in fields: + value = ( + getattr(self, field.attname) if raw else field.pre_save(self, False) + ) + if hasattr(value, "resolve_expression"): + returning_fields.append(field) + elif field.db_returning: + returning_fields.remove(field) results = self._do_insert( cls._base_manager, using, fields, returning_fields, raw ) @@ -1203,8 +1216,13 @@ class Model(AltersData, metaclass=ModelBase): ) def _assign_returned_values(self, returned_values, returning_fields): - for value, field in zip(returned_values, returning_fields): + returning_fields_iter = iter(returning_fields) + for value, field in zip(returned_values, returning_fields_iter): setattr(self, field.attname, value) + # Defer all fields that were meant to be updated with their database + # resolved values but couldn't as they are effectively stale. + for field in returning_fields_iter: + self.__dict__.pop(field.attname, None) def _prepare_related_fields_for_save(self, operation_name, fields=None): # Ensure that a model instance without a PK hasn't been assigned to |
