summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
Diffstat (limited to 'django')
-rw-r--r--django/db/models/expressions.py34
-rw-r--r--django/db/models/fields/__init__.py12
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