mirror of
https://github.com/django/django.git
synced 2025-06-05 03:29:12 +00:00
Refs #36064 -- Added Model.has_db_default() to encapsulate NOT_PROVIDED checks.
This avoids many awkward checks against NOT_PROVIDED and provides symmetry with Field.has_default() which is also the reason why it wasn't made a property.
This commit is contained in:
parent
0fb51ec5a0
commit
9fa4d07ce0
@ -13,7 +13,7 @@ from django.db.backends.ddl_references import (
|
|||||||
Table,
|
Table,
|
||||||
)
|
)
|
||||||
from django.db.backends.utils import names_digest, split_identifier, truncate_name
|
from django.db.backends.utils import names_digest, split_identifier, truncate_name
|
||||||
from django.db.models import NOT_PROVIDED, Deferrable, Index
|
from django.db.models import Deferrable, Index
|
||||||
from django.db.models.fields.composite import CompositePrimaryKey
|
from django.db.models.fields.composite import CompositePrimaryKey
|
||||||
from django.db.models.sql import Query
|
from django.db.models.sql import Query
|
||||||
from django.db.transaction import TransactionManagementError, atomic
|
from django.db.transaction import TransactionManagementError, atomic
|
||||||
@ -318,7 +318,7 @@ class BaseDatabaseSchemaEditor:
|
|||||||
# Work out nullability.
|
# Work out nullability.
|
||||||
null = field.null
|
null = field.null
|
||||||
# Add database default.
|
# Add database default.
|
||||||
if field.db_default is not NOT_PROVIDED:
|
if field.has_db_default():
|
||||||
default_sql, default_params = self.db_default_sql(field)
|
default_sql, default_params = self.db_default_sql(field)
|
||||||
yield f"DEFAULT {default_sql}"
|
yield f"DEFAULT {default_sql}"
|
||||||
params.extend(default_params)
|
params.extend(default_params)
|
||||||
@ -775,7 +775,7 @@ class BaseDatabaseSchemaEditor:
|
|||||||
self.execute(sql, params or None)
|
self.execute(sql, params or None)
|
||||||
# Drop the default if we need to
|
# Drop the default if we need to
|
||||||
if (
|
if (
|
||||||
field.db_default is NOT_PROVIDED
|
not field.has_db_default()
|
||||||
and not self.skip_default_on_alter(field)
|
and not self.skip_default_on_alter(field)
|
||||||
and self.effective_default(field) is not None
|
and self.effective_default(field) is not None
|
||||||
):
|
):
|
||||||
@ -1108,15 +1108,15 @@ class BaseDatabaseSchemaEditor:
|
|||||||
actions.append(fragment)
|
actions.append(fragment)
|
||||||
post_actions.extend(other_actions)
|
post_actions.extend(other_actions)
|
||||||
|
|
||||||
if new_field.db_default is not NOT_PROVIDED:
|
if new_field.has_db_default():
|
||||||
if (
|
if (
|
||||||
old_field.db_default is NOT_PROVIDED
|
not old_field.has_db_default()
|
||||||
or new_field.db_default != old_field.db_default
|
or new_field.db_default != old_field.db_default
|
||||||
):
|
):
|
||||||
actions.append(
|
actions.append(
|
||||||
self._alter_column_database_default_sql(model, old_field, new_field)
|
self._alter_column_database_default_sql(model, old_field, new_field)
|
||||||
)
|
)
|
||||||
elif old_field.db_default is not NOT_PROVIDED:
|
elif old_field.has_db_default():
|
||||||
actions.append(
|
actions.append(
|
||||||
self._alter_column_database_default_sql(
|
self._alter_column_database_default_sql(
|
||||||
model, old_field, new_field, drop=True
|
model, old_field, new_field, drop=True
|
||||||
@ -1130,11 +1130,7 @@ class BaseDatabaseSchemaEditor:
|
|||||||
# 4. Drop the default again.
|
# 4. Drop the default again.
|
||||||
# Default change?
|
# Default change?
|
||||||
needs_database_default = False
|
needs_database_default = False
|
||||||
if (
|
if old_field.null and not new_field.null and not new_field.has_db_default():
|
||||||
old_field.null
|
|
||||||
and not new_field.null
|
|
||||||
and new_field.db_default is NOT_PROVIDED
|
|
||||||
):
|
|
||||||
old_default = self.effective_default(old_field)
|
old_default = self.effective_default(old_field)
|
||||||
new_default = self.effective_default(new_field)
|
new_default = self.effective_default(new_field)
|
||||||
if (
|
if (
|
||||||
@ -1153,7 +1149,7 @@ class BaseDatabaseSchemaEditor:
|
|||||||
null_actions.append(fragment)
|
null_actions.append(fragment)
|
||||||
# Only if we have a default and there is a change from NULL to NOT NULL
|
# Only if we have a default and there is a change from NULL to NOT NULL
|
||||||
four_way_default_alteration = (
|
four_way_default_alteration = (
|
||||||
new_field.has_default() or new_field.db_default is not NOT_PROVIDED
|
new_field.has_default() or new_field.has_db_default()
|
||||||
) and (old_field.null and not new_field.null)
|
) and (old_field.null and not new_field.null)
|
||||||
if actions or null_actions:
|
if actions or null_actions:
|
||||||
if not four_way_default_alteration:
|
if not four_way_default_alteration:
|
||||||
@ -1175,7 +1171,7 @@ class BaseDatabaseSchemaEditor:
|
|||||||
params,
|
params,
|
||||||
)
|
)
|
||||||
if four_way_default_alteration:
|
if four_way_default_alteration:
|
||||||
if new_field.db_default is NOT_PROVIDED:
|
if not new_field.has_db_default():
|
||||||
default_sql = "%s"
|
default_sql = "%s"
|
||||||
params = [new_default]
|
params = [new_default]
|
||||||
else:
|
else:
|
||||||
|
@ -222,7 +222,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
|||||||
Keep the NULL and DEFAULT properties of the old field. If it has
|
Keep the NULL and DEFAULT properties of the old field. If it has
|
||||||
changed, it will be handled separately.
|
changed, it will be handled separately.
|
||||||
"""
|
"""
|
||||||
if field.db_default is not NOT_PROVIDED:
|
if field.has_db_default():
|
||||||
default_sql, params = self.db_default_sql(field)
|
default_sql, params = self.db_default_sql(field)
|
||||||
default_sql %= tuple(self.quote_value(p) for p in params)
|
default_sql %= tuple(self.quote_value(p) for p in params)
|
||||||
new_type += f" DEFAULT {default_sql}"
|
new_type += f" DEFAULT {default_sql}"
|
||||||
@ -266,7 +266,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
|||||||
return f" COMMENT {comment_sql}"
|
return f" COMMENT {comment_sql}"
|
||||||
|
|
||||||
def _alter_column_null_sql(self, model, old_field, new_field):
|
def _alter_column_null_sql(self, model, old_field, new_field):
|
||||||
if new_field.db_default is NOT_PROVIDED:
|
if not new_field.has_db_default():
|
||||||
return super()._alter_column_null_sql(model, old_field, new_field)
|
return super()._alter_column_null_sql(model, old_field, new_field)
|
||||||
|
|
||||||
new_db_params = new_field.db_parameters(connection=self.connection)
|
new_db_params = new_field.db_parameters(connection=self.connection)
|
||||||
|
@ -6,7 +6,7 @@ from django.db import NotSupportedError
|
|||||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||||
from django.db.backends.ddl_references import Statement
|
from django.db.backends.ddl_references import Statement
|
||||||
from django.db.backends.utils import strip_quotes
|
from django.db.backends.utils import strip_quotes
|
||||||
from django.db.models import NOT_PROVIDED, CompositePrimaryKey, UniqueConstraint
|
from django.db.models import CompositePrimaryKey, UniqueConstraint
|
||||||
|
|
||||||
|
|
||||||
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
@ -144,7 +144,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
|||||||
body[create_field.name] = create_field
|
body[create_field.name] = create_field
|
||||||
# Choose a default and insert it into the copy map
|
# Choose a default and insert it into the copy map
|
||||||
if (
|
if (
|
||||||
create_field.db_default is NOT_PROVIDED
|
not create_field.has_db_default()
|
||||||
and not (create_field.many_to_many or create_field.generated)
|
and not (create_field.many_to_many or create_field.generated)
|
||||||
and create_field.concrete
|
and create_field.concrete
|
||||||
):
|
):
|
||||||
@ -161,7 +161,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
|||||||
if new_field.generated:
|
if new_field.generated:
|
||||||
continue
|
continue
|
||||||
if old_field.null and not new_field.null:
|
if old_field.null and not new_field.null:
|
||||||
if new_field.db_default is NOT_PROVIDED:
|
if not new_field.has_db_default():
|
||||||
default = self.prepare_default(self.effective_default(new_field))
|
default = self.prepare_default(self.effective_default(new_field))
|
||||||
else:
|
else:
|
||||||
default, _ = self.db_default_sql(new_field)
|
default, _ = self.db_default_sql(new_field)
|
||||||
@ -321,10 +321,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
|||||||
or self.effective_default(field) is not None
|
or self.effective_default(field) is not None
|
||||||
# Fields with non-constant defaults cannot by handled by ALTER
|
# Fields with non-constant defaults cannot by handled by ALTER
|
||||||
# TABLE ADD COLUMN statement.
|
# TABLE ADD COLUMN statement.
|
||||||
or (
|
or (field.has_db_default() and not isinstance(field.db_default, Value))
|
||||||
field.db_default is not NOT_PROVIDED
|
|
||||||
and not isinstance(field.db_default, Value)
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
self._remake_table(model, create_field=field)
|
self._remake_table(model, create_field=field)
|
||||||
else:
|
else:
|
||||||
|
@ -1135,7 +1135,7 @@ class MigrationAutodetector:
|
|||||||
preserve_default = (
|
preserve_default = (
|
||||||
field.null
|
field.null
|
||||||
or field.has_default()
|
or field.has_default()
|
||||||
or field.db_default is not models.NOT_PROVIDED
|
or field.has_db_default()
|
||||||
or field.many_to_many
|
or field.many_to_many
|
||||||
or (field.blank and field.empty_strings_allowed)
|
or (field.blank and field.empty_strings_allowed)
|
||||||
or (isinstance(field, time_fields) and field.auto_now)
|
or (isinstance(field, time_fields) and field.auto_now)
|
||||||
@ -1150,11 +1150,7 @@ class MigrationAutodetector:
|
|||||||
field.default = self.questioner.ask_not_null_addition(
|
field.default = self.questioner.ask_not_null_addition(
|
||||||
field_name, model_name
|
field_name, model_name
|
||||||
)
|
)
|
||||||
if (
|
if field.unique and field.has_default() and callable(field.default):
|
||||||
field.unique
|
|
||||||
and field.default is not models.NOT_PROVIDED
|
|
||||||
and callable(field.default)
|
|
||||||
):
|
|
||||||
self.questioner.ask_unique_callable_default_addition(field_name, model_name)
|
self.questioner.ask_unique_callable_default_addition(field_name, model_name)
|
||||||
self.add_operation(
|
self.add_operation(
|
||||||
app_label,
|
app_label,
|
||||||
@ -1296,7 +1292,7 @@ class MigrationAutodetector:
|
|||||||
old_field.null
|
old_field.null
|
||||||
and not new_field.null
|
and not new_field.null
|
||||||
and not new_field.has_default()
|
and not new_field.has_default()
|
||||||
and new_field.db_default is models.NOT_PROVIDED
|
and not new_field.has_db_default()
|
||||||
and not new_field.many_to_many
|
and not new_field.many_to_many
|
||||||
):
|
):
|
||||||
field = new_field.clone()
|
field = new_field.clone()
|
||||||
|
@ -1118,10 +1118,7 @@ class Model(AltersData, metaclass=ModelBase):
|
|||||||
and not force_insert
|
and not force_insert
|
||||||
and not force_update
|
and not force_update
|
||||||
and self._state.adding
|
and self._state.adding
|
||||||
and (
|
and (meta.pk.has_default() or meta.pk.has_db_default())
|
||||||
(meta.pk.default and meta.pk.default is not NOT_PROVIDED)
|
|
||||||
or (meta.pk.db_default and meta.pk.db_default is not NOT_PROVIDED)
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
force_insert = True
|
force_insert = True
|
||||||
# If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
|
# If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
|
||||||
|
@ -391,7 +391,7 @@ class Field(RegisterLookupMixin):
|
|||||||
from django.db.models.expressions import Value
|
from django.db.models.expressions import Value
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.db_default is NOT_PROVIDED
|
not self.has_db_default()
|
||||||
or (
|
or (
|
||||||
isinstance(self.db_default, Value)
|
isinstance(self.db_default, Value)
|
||||||
or not hasattr(self.db_default, "resolve_expression")
|
or not hasattr(self.db_default, "resolve_expression")
|
||||||
@ -933,8 +933,7 @@ class Field(RegisterLookupMixin):
|
|||||||
def db_returning(self):
|
def db_returning(self):
|
||||||
"""Private API intended only to be used by Django itself."""
|
"""Private API intended only to be used by Django itself."""
|
||||||
return (
|
return (
|
||||||
self.db_default is not NOT_PROVIDED
|
self.has_db_default() and connection.features.can_return_columns_from_insert
|
||||||
and connection.features.can_return_columns_from_insert
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_attributes_from_name(self, name):
|
def set_attributes_from_name(self, name):
|
||||||
@ -1016,6 +1015,10 @@ class Field(RegisterLookupMixin):
|
|||||||
"""Return a boolean of whether this field has a default value."""
|
"""Return a boolean of whether this field has a default value."""
|
||||||
return self.default is not NOT_PROVIDED
|
return self.default is not NOT_PROVIDED
|
||||||
|
|
||||||
|
def has_db_default(self):
|
||||||
|
"""Return a boolean of whether this field has a db_default value."""
|
||||||
|
return self.db_default is not NOT_PROVIDED
|
||||||
|
|
||||||
def get_default(self):
|
def get_default(self):
|
||||||
"""Return the default value for this field."""
|
"""Return the default value for this field."""
|
||||||
return self._get_default()
|
return self._get_default()
|
||||||
@ -1027,7 +1030,7 @@ class Field(RegisterLookupMixin):
|
|||||||
return self.default
|
return self.default
|
||||||
return lambda: self.default
|
return lambda: self.default
|
||||||
|
|
||||||
if self.db_default is not NOT_PROVIDED:
|
if self.has_db_default():
|
||||||
from django.db.models.expressions import DatabaseDefault
|
from django.db.models.expressions import DatabaseDefault
|
||||||
|
|
||||||
return lambda: DatabaseDefault(
|
return lambda: DatabaseDefault(
|
||||||
@ -1045,9 +1048,7 @@ class Field(RegisterLookupMixin):
|
|||||||
@cached_property
|
@cached_property
|
||||||
def _db_default_expression(self):
|
def _db_default_expression(self):
|
||||||
db_default = self.db_default
|
db_default = self.db_default
|
||||||
if db_default is not NOT_PROVIDED and not hasattr(
|
if self.has_db_default() and not hasattr(db_default, "resolve_expression"):
|
||||||
db_default, "resolve_expression"
|
|
||||||
):
|
|
||||||
from django.db.models.expressions import Value
|
from django.db.models.expressions import Value
|
||||||
|
|
||||||
db_default = Value(db_default, self)
|
db_default = Value(db_default, self)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user