1
0
mirror of https://github.com/django/django.git synced 2025-10-28 16:16:12 +00:00

Fixed #21961 -- Added support for database-level delete options for ForeignKey.

Thanks Simon Charette for pair programming.

Co-authored-by: Nick Stefan <NickStefan12@gmail.com>
Co-authored-by: Akash Kumar Sen <71623442+Akash-Kumar-Sen@users.noreply.github.com>
Co-authored-by: Simon Charette <charette.s@gmail.com>
This commit is contained in:
Mariusz Felisiak
2025-10-18 15:03:50 +02:00
committed by GitHub
parent b1e0262c9f
commit 0c487aa3a7
33 changed files with 838 additions and 67 deletions

View File

@@ -1699,11 +1699,11 @@ relation works.
.. attribute:: ForeignKey.on_delete
When an object referenced by a :class:`ForeignKey` is deleted, Django will
emulate the behavior of the SQL constraint specified by the
:attr:`on_delete` argument. For example, if you have a nullable
:class:`ForeignKey` and you want it to be set null when the referenced
object is deleted::
When an object referenced by a :class:`ForeignKey` is deleted, the
referring objects need updating. The :attr:`on_delete` argument specifies
how this is done, and whether Django or your database makes the updates.
For example, if you have a nullable :class:`ForeignKey` and you want Django
to set it to ``None`` when the referenced object is deleted::
user = models.ForeignKey(
User,
@@ -1712,8 +1712,21 @@ relation works.
null=True,
)
``on_delete`` doesn't create an SQL constraint in the database. Support for
database-level cascade options :ticket:`may be implemented later <21961>`.
The possible values for :attr:`~ForeignKey.on_delete` are listed below.
Import them from :mod:`django.db.models`. The ``DB_*`` variants use the
database to prevent deletions or update referring objects, whilst the other
values make Django perform the relevant actions.
The database variants are more efficient because they avoid fetching
related objects, but ``pre_delete`` and ``post_delete`` signals won't be
sent when ``DB_CASCADE`` is used.
The database variants cannot be mixed with Python variants (other than
:attr:`DO_NOTHING`) in the same model and in models related to each other.
.. versionchanged:: 6.1
Support for ``DB_*`` variants of the ``on_delete`` attribute was added.
The possible values for :attr:`~ForeignKey.on_delete` are found in
:mod:`django.db.models`:
@@ -1729,6 +1742,13 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
:data:`~django.db.models.signals.post_delete` signals are sent for all
deleted objects.
* .. attribute:: DB_CASCADE
.. versionadded:: 6.1
Cascade deletes. Database-level version of :attr:`CASCADE`: the database
deletes referred-to rows and the one containing the ``ForeignKey``.
* .. attribute:: PROTECT
Prevent deletion of the referenced object by raising
@@ -1782,11 +1802,30 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
Set the :class:`ForeignKey` null; this is only possible if
:attr:`~Field.null` is ``True``.
* .. attribute:: DB_SET_NULL
.. versionadded:: 6.1
Set the :class:`ForeignKey` value to ``NULL``. This is only possible if
:attr:`~Field.null` is ``True``. Database-level version of
:attr:`SET_NULL`.
* .. attribute:: SET_DEFAULT
Set the :class:`ForeignKey` to its default value; a default for the
:class:`ForeignKey` must be set.
* .. attribute:: DB_SET_DEFAULT
.. versionadded:: 6.1
Set the :class:`ForeignKey` value to its :attr:`Field.db_default` value,
which must be set. If a row in the referenced table is deleted, the foreign
key values in the referencing table will be updated to their
:attr:`Field.db_default` values.
``DB_SET_DEFAULT`` is not supported on MySQL and MariaDB.
* .. function:: SET()
Set the :class:`ForeignKey` to the value passed to

View File

@@ -695,7 +695,11 @@ Issues an SQL ``DELETE`` for the object. This only deletes the object in the
database; the Python instance will still exist and will still have data in
its fields, except for the primary key set to ``None``. This method returns the
number of objects deleted and a dictionary with the number of deletions per
object type.
object type. The return value will count instances from related models if
Django is emulating cascade behavior via Python :attr:`~ForeignKey.on_delete`
variants. Otherwise, for database variants such as
:attr:`~django.db.models.DB_CASCADE`, the return value will report only
instances of the :class:`.QuerySet`'s model.
For more details, including how to delete objects in bulk, see
:ref:`topics-db-queries-delete`.
@@ -707,6 +711,10 @@ Sometimes with :ref:`multi-table inheritance <multi-table-inheritance>` you may
want to delete only a child model's data. Specifying ``keep_parents=True`` will
keep the parent model's data.
.. versionchanged:: 6.1
Support for the ``DB_*`` variants of ``on_delete`` attribute was added.
Pickling objects
================

View File

@@ -3036,7 +3036,11 @@ unique field in the order that is specified without conflicts. For example::
Performs an SQL delete query on all rows in the :class:`.QuerySet` and
returns the number of objects deleted and a dictionary with the number of
deletions per object type.
deletions per object type. The return value will count instances from related
models if Django is emulating cascade behavior via Python
:attr:`~django.db.models.ForeignKey.on_delete` variants. Otherwise, for
database variants such as :attr:`~django.db.models.DB_CASCADE`, the return
value will report only instances of the :class:`.QuerySet`'s model.
The ``delete()`` is applied instantly. You cannot call ``delete()`` on a
:class:`.QuerySet` that has had a slice taken or can otherwise no longer be
@@ -3073,13 +3077,20 @@ The ``delete()`` method does a bulk delete and does not call any ``delete()``
methods on your models. It does, however, emit the
:data:`~django.db.models.signals.pre_delete` and
:data:`~django.db.models.signals.post_delete` signals for all deleted objects
(including cascaded deletions).
(including cascaded deletions). Signals won't be sent when ``DB_CASCADE`` is
used. Also, ``delete()`` doesn't return information about objects deleted from
database variants (``DB_*``) of the
:attr:`~django.db.models.ForeignKey.on_delete` argument, e.g. ``DB_CASCADE``.
Django needs to fetch objects into memory to send signals and handle cascades.
However, if there are no cascades and no signals, then Django may take a
fast-path and delete objects without fetching into memory. For large
deletes this can result in significantly reduced memory usage. The amount of
executed queries can be reduced, too.
Django wont need to fetch objects into memory when deleting them in the
following cases:
#. If related fields use ``DB_*`` options.
#. If there are no cascades and no delete signal receivers.
In these cases, Django may take a fast path and delete objects without fetching
them, which can result in significantly reduced memory usage and fewer executed
queries.
ForeignKeys which are set to :attr:`~django.db.models.ForeignKey.on_delete`
``DO_NOTHING`` do not prevent taking the fast-path in deletion.
@@ -3087,6 +3098,10 @@ ForeignKeys which are set to :attr:`~django.db.models.ForeignKey.on_delete`
Note that the queries generated in object deletion is an implementation
detail subject to change.
.. versionchanged:: 6.1
Support for the ``DB_*`` variants of ``on_delete`` attribute was added.
``as_manager()``
~~~~~~~~~~~~~~~~