Fixed #470 -- Added support for database defaults on fields.

Special thanks to Hannes Ljungberg for finding multiple implementation
gaps.

Thanks also to Simon Charette, Adam Johnson, and Mariusz Felisiak for
reviews.
This commit is contained in:
Ian Foote 2020-11-22 22:27:57 +00:00 committed by Mariusz Felisiak
parent 599f3e2cda
commit 7414704e88
32 changed files with 1089 additions and 34 deletions

View file

@ -996,6 +996,13 @@ calling the appropriate methods on the wrapped expression.
.. class:: Expression
.. attribute:: allowed_default
.. versionadded:: 5.0
Tells Django that this expression can be used in
:attr:`Field.db_default`. Defaults to ``False``.
.. attribute:: contains_aggregate
Tells Django that this expression contains an aggregate and that a

View file

@ -351,6 +351,38 @@ looking at your Django code. For example::
db_comment="Date and time when the article was published",
)
``db_default``
--------------
.. versionadded:: 5.0
.. attribute:: Field.db_default
The database-computed default value for this field. This can be a literal value
or a database function, such as :class:`~django.db.models.functions.Now`::
created = models.DateTimeField(db_default=Now())
More complex expressions can be used, as long as they are made from literals
and database functions::
month_due = models.DateField(
db_default=TruncMonth(
Now() + timedelta(days=90),
output_field=models.DateField(),
)
)
Database defaults cannot reference other fields or models. For example, this is
invalid::
end = models.IntegerField(db_default=F("start") + 50)
If both ``db_default`` and :attr:`Field.default` are set, ``default`` will take
precedence when creating instances in Python code. ``db_default`` will still be
set at the database level and will be used when inserting rows outside of the
ORM or when adding a new field in a migration.
``db_index``
------------
@ -408,6 +440,9 @@ The default value is used when new model instances are created and a value
isn't provided for the field. When the field is a primary key, the default is
also used when the field is set to ``None``.
The default value can also be set at the database level with
:attr:`Field.db_default`.
``editable``
------------

View file

@ -541,7 +541,8 @@ You may have noticed Django database objects use the same ``save()`` method
for creating and changing objects. Django abstracts the need to use ``INSERT``
or ``UPDATE`` SQL statements. Specifically, when you call ``save()`` and the
object's primary key attribute does **not** define a
:attr:`~django.db.models.Field.default`, Django follows this algorithm:
:attr:`~django.db.models.Field.default` or
:attr:`~django.db.models.Field.db_default`, Django follows this algorithm:
* If the object's primary key attribute is set to a value that evaluates to
``True`` (i.e., a value other than ``None`` or the empty string), Django
@ -551,9 +552,10 @@ object's primary key attribute does **not** define a
exist in the database), Django executes an ``INSERT``.
If the object's primary key attribute defines a
:attr:`~django.db.models.Field.default` then Django executes an ``UPDATE`` if
it is an existing model instance and primary key is set to a value that exists
in the database. Otherwise, Django executes an ``INSERT``.
:attr:`~django.db.models.Field.default` or
:attr:`~django.db.models.Field.db_default` then Django executes an ``UPDATE``
if it is an existing model instance and primary key is set to a value that
exists in the database. Otherwise, Django executes an ``INSERT``.
The one gotcha here is that you should be careful not to specify a primary-key
value explicitly when saving new objects, if you cannot guarantee the
@ -570,6 +572,10 @@ which returns ``NULL``. In such cases it is possible to revert to the old
algorithm by setting the :attr:`~django.db.models.Options.select_on_save`
option to ``True``.
.. versionchanged:: 5.0
The ``Field.db_default`` parameter was added.
.. _ref-models-force-insert:
Forcing an INSERT or UPDATE