1
0
mirror of https://github.com/django/django.git synced 2024-12-23 01:25:58 +00:00

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:
Simon Charette 2024-12-09 22:14:59 -05:00
parent e165c6ef09
commit e197a2b222
No known key found for this signature in database
6 changed files with 27 additions and 40 deletions

View File

@ -13,7 +13,7 @@ from django.db.backends.ddl_references import (
Table,
)
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.sql import Query
from django.db.transaction import TransactionManagementError, atomic
@ -318,7 +318,7 @@ class BaseDatabaseSchemaEditor:
# Work out nullability.
null = field.null
# 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)
yield f"DEFAULT {default_sql}"
params.extend(default_params)
@ -775,7 +775,7 @@ class BaseDatabaseSchemaEditor:
self.execute(sql, params or None)
# Drop the default if we need to
if (
field.db_default is NOT_PROVIDED
not field.has_db_default()
and not self.skip_default_on_alter(field)
and self.effective_default(field) is not None
):
@ -1108,15 +1108,15 @@ class BaseDatabaseSchemaEditor:
actions.append(fragment)
post_actions.extend(other_actions)
if new_field.db_default is not NOT_PROVIDED:
if new_field.has_db_default():
if (
old_field.db_default is NOT_PROVIDED
not old_field.has_db_default()
or new_field.db_default != old_field.db_default
):
actions.append(
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(
self._alter_column_database_default_sql(
model, old_field, new_field, drop=True
@ -1130,11 +1130,7 @@ class BaseDatabaseSchemaEditor:
# 4. Drop the default again.
# Default change?
needs_database_default = False
if (
old_field.null
and not new_field.null
and new_field.db_default is NOT_PROVIDED
):
if old_field.null and not new_field.null and not new_field.has_db_default():
old_default = self.effective_default(old_field)
new_default = self.effective_default(new_field)
if (
@ -1153,7 +1149,7 @@ class BaseDatabaseSchemaEditor:
null_actions.append(fragment)
# Only if we have a default and there is a change from NULL to NOT NULL
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)
if actions or null_actions:
if not four_way_default_alteration:
@ -1175,7 +1171,7 @@ class BaseDatabaseSchemaEditor:
params,
)
if four_way_default_alteration:
if new_field.db_default is NOT_PROVIDED:
if not new_field.has_db_default():
default_sql = "%s"
params = [new_default]
else:

View File

@ -222,7 +222,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
Keep the NULL and DEFAULT properties of the old field. If it has
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 %= tuple(self.quote_value(p) for p in params)
new_type += f" DEFAULT {default_sql}"
@ -266,7 +266,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
return f" COMMENT {comment_sql}"
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)
new_db_params = new_field.db_parameters(connection=self.connection)

View File

@ -6,7 +6,7 @@ from django.db import NotSupportedError
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.backends.ddl_references import Statement
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):
@ -144,7 +144,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
body[create_field.name] = create_field
# Choose a default and insert it into the copy map
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 create_field.concrete
):
@ -161,7 +161,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
if new_field.generated:
continue
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))
else:
default, _ = self.db_default_sql(new_field)
@ -321,10 +321,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
or self.effective_default(field) is not None
# Fields with non-constant defaults cannot by handled by ALTER
# TABLE ADD COLUMN statement.
or (
field.db_default is not NOT_PROVIDED
and not isinstance(field.db_default, Value)
)
or (field.has_db_default() and not isinstance(field.db_default, Value))
):
self._remake_table(model, create_field=field)
else:

View File

@ -1135,7 +1135,7 @@ class MigrationAutodetector:
preserve_default = (
field.null
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.blank and field.empty_strings_allowed)
or (isinstance(field, time_fields) and field.auto_now)
@ -1150,11 +1150,7 @@ class MigrationAutodetector:
field.default = self.questioner.ask_not_null_addition(
field_name, model_name
)
if (
field.unique
and field.default is not models.NOT_PROVIDED
and callable(field.default)
):
if field.unique and field.has_default() and callable(field.default):
self.questioner.ask_unique_callable_default_addition(field_name, model_name)
self.add_operation(
app_label,
@ -1296,7 +1292,7 @@ class MigrationAutodetector:
old_field.null
and not new_field.null
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
):
field = new_field.clone()

View File

@ -1117,10 +1117,7 @@ class Model(AltersData, metaclass=ModelBase):
and not force_insert
and not force_update
and self._state.adding
and (
(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)
)
and (meta.pk.has_default() or meta.pk.has_db_default())
):
force_insert = True
# If possible, try an UPDATE. If that doesn't update anything, do an INSERT.

View File

@ -391,7 +391,7 @@ class Field(RegisterLookupMixin):
from django.db.models.expressions import Value
if (
self.db_default is NOT_PROVIDED
not self.has_db_default()
or (
isinstance(self.db_default, Value)
or not hasattr(self.db_default, "resolve_expression")
@ -933,8 +933,7 @@ class Field(RegisterLookupMixin):
def db_returning(self):
"""Private API intended only to be used by Django itself."""
return (
self.db_default is not NOT_PROVIDED
and connection.features.can_return_columns_from_insert
self.has_db_default() and connection.features.can_return_columns_from_insert
)
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 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):
"""Return the default value for this field."""
return self._get_default()
@ -1027,7 +1030,7 @@ class Field(RegisterLookupMixin):
return 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
return lambda: DatabaseDefault(
@ -1045,9 +1048,7 @@ class Field(RegisterLookupMixin):
@cached_property
def _db_default_expression(self):
db_default = self.db_default
if db_default is not NOT_PROVIDED and not hasattr(
db_default, "resolve_expression"
):
if self.has_db_default() and not hasattr(db_default, "resolve_expression"):
from django.db.models.expressions import Value
db_default = Value(db_default, self)