diff options
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/models/expressions.py | 34 | ||||
| -rw-r--r-- | django/db/models/fields/__init__.py | 12 |
2 files changed, 37 insertions, 9 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 7779173f3c..0f5e68b0d4 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -1250,9 +1250,41 @@ class Star(Expression): class DatabaseDefault(Expression): - """Placeholder expression for the database default in an insert query.""" + """ + Expression to use DEFAULT keyword during insert otherwise the underlying expression. + """ + + def __init__(self, expression, output_field=None): + super().__init__(output_field) + self.expression = expression + + def get_source_expressions(self): + return [self.expression] + + def set_source_expressions(self, exprs): + (self.expression,) = exprs + + def resolve_expression( + self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False + ): + resolved_expression = self.expression.resolve_expression( + query=query, + allow_joins=allow_joins, + reuse=reuse, + summarize=summarize, + for_save=for_save, + ) + # Defaults used outside an INSERT context should resolve to their + # underlying expression. + if not for_save: + return resolved_expression + return DatabaseDefault( + resolved_expression, output_field=self._output_field_or_none + ) def as_sql(self, compiler, connection): + if not connection.features.supports_default_keyword_in_insert: + return compiler.compile(self.expression) return "DEFAULT", [] diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 796c4d23c4..d1f31f0211 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -983,13 +983,7 @@ class Field(RegisterLookupMixin): def pre_save(self, model_instance, add): """Return field's value just before saving.""" - value = getattr(model_instance, self.attname) - if not connection.features.supports_default_keyword_in_insert: - from django.db.models.expressions import DatabaseDefault - - if isinstance(value, DatabaseDefault): - return self._db_default_expression - return value + return getattr(model_instance, self.attname) def get_prep_value(self, value): """Perform preliminary non-db specific value checks and conversions.""" @@ -1031,7 +1025,9 @@ class Field(RegisterLookupMixin): if self.db_default is not NOT_PROVIDED: from django.db.models.expressions import DatabaseDefault - return DatabaseDefault + return lambda: DatabaseDefault( + self._db_default_expression, output_field=self + ) if ( not self.empty_strings_allowed |
