summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2010-11-09 16:46:42 +0000
committerCarl Meyer <carl@oddbird.net>2010-11-09 16:46:42 +0000
commit616b30227d901a7452810a9ffaa55eaf186dc9e1 (patch)
treea90a046c56bc8c25fc3ce5c0021c02b8ff77c0ba /docs
parent3ba3294c6b5ad413731223a9e46064a8e132acd2 (diff)
Fixed #7539, #13067 -- Added on_delete argument to ForeignKey to control cascade behavior. Also refactored deletion for efficiency and code clarity. Many thanks to Johannes Dollinger and Michael Glassford for extensive work on the patch, and to Alex Gaynor, Russell Keith-Magee, and Jacob Kaplan-Moss for review.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14507 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/contrib/contenttypes.txt10
-rw-r--r--docs/ref/models/fields.txt47
-rw-r--r--docs/ref/models/querysets.txt12
-rw-r--r--docs/releases/1.3.txt13
-rw-r--r--docs/topics/db/queries.txt13
5 files changed, 87 insertions, 8 deletions
diff --git a/docs/ref/contrib/contenttypes.txt b/docs/ref/contrib/contenttypes.txt
index b6956512ad..4a2e213ffb 100644
--- a/docs/ref/contrib/contenttypes.txt
+++ b/docs/ref/contrib/contenttypes.txt
@@ -341,6 +341,16 @@ pointing at it will be deleted as well. In the example above, this means that
if a ``Bookmark`` object were deleted, any ``TaggedItem`` objects pointing at
it would be deleted at the same time.
+.. versionadded:: 1.3
+
+Unlike :class:`~django.db.models.ForeignKey`,
+:class:`~django.contrib.contenttypes.generic.GenericForeignKey` does not accept
+an :attr:`~django.db.models.ForeignKey.on_delete` argument to customize this
+behavior; if desired, you can avoid the cascade-deletion simply by not using
+:class:`~django.contrib.contenttypes.generic.GenericRelation`, and alternate
+behavior can be provided via the :data:`~django.db.models.signals.pre_delete`
+signal.
+
Generic relations and aggregation
---------------------------------
diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
index cebd893ee9..7300f4d75d 100644
--- a/docs/ref/models/fields.txt
+++ b/docs/ref/models/fields.txt
@@ -930,7 +930,7 @@ define the details of how the relation works.
If you'd prefer Django didn't create a backwards relation, set ``related_name``
to ``'+'``. For example, this will ensure that the ``User`` model won't get a
backwards relation to this model::
-
+
user = models.ForeignKey(User, related_name='+')
.. attribute:: ForeignKey.to_field
@@ -938,6 +938,51 @@ define the details of how the relation works.
The field on the related object that the relation is to. By default, Django
uses the primary key of the related object.
+.. versionadded:: 1.3
+
+.. attribute:: ForeignKey.on_delete
+
+ When an object referenced by a :class:`ForeignKey` is deleted, Django by
+ default emulates the behavior of the SQL constraint ``ON DELETE CASCADE``
+ and also deletes the object containing the ``ForeignKey``. This behavior
+ can be overridden by specifying 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::
+
+ user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
+
+ The possible values for :attr:`on_delete` are found in
+ :mod:`django.db.models`:
+
+ * :attr:`~django.db.models.CASCADE`: Cascade deletes; the default.
+
+ * :attr:`~django.db.models.PROTECT`: Prevent deletion of the referenced
+ object by raising :exc:`django.db.IntegrityError`.
+
+ * :attr:`~django.db.models.SET_NULL`: Set the :class:`ForeignKey` null;
+ this is only possible if :attr:`null` is ``True``.
+
+ * :attr:`~django.db.models.SET_DEFAULT`: Set the :class:`ForeignKey` to its
+ default value; a default for the :class:`ForeignKey` must be set.
+
+ * :func:`~django.db.models.SET()`: Set the :class:`ForeignKey` to the value
+ passed to :func:`~django.db.models.SET()`, or if a callable is passed in,
+ the result of calling it. In most cases, passing a callable will be
+ necessary to avoid executing queries at the time your models.py is
+ imported::
+
+ def get_sentinel_user():
+ return User.objects.get_or_create(username='deleted')[0]
+
+ class MyModel(models.Model):
+ user = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))
+
+ * :attr:`~django.db.models.DO_NOTHING`: Take no action. If your database
+ backend enforces referential integrity, this will cause an
+ :exc:`~django.db.IntegrityError` unless you manually add a SQL ``ON
+ DELETE`` constraint to the database field (perhaps using
+ :ref:`initial sql<initial-sql>`).
+
.. _ref-manytomany:
``ManyToManyField``
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 025c50966b..5659579955 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -1263,14 +1263,20 @@ For example, to delete all the entries in a particular blog::
# Delete all the entries belonging to this Blog.
>>> Entry.objects.filter(blog=b).delete()
-Django emulates the SQL constraint ``ON DELETE CASCADE`` -- in other words, any
-objects with foreign keys pointing at the objects to be deleted will be deleted
-along with them. For example::
+By default, Django's :class:`~django.db.models.ForeignKey` emulates the SQL
+constraint ``ON DELETE CASCADE`` -- in other words, any objects with foreign
+keys pointing at the objects to be deleted will be deleted along with them.
+For example::
blogs = Blog.objects.all()
# This will delete all Blogs and all of their Entry objects.
blogs.delete()
+.. versionadded:: 1.3
+ This cascade behavior is customizable via the
+ :attr:`~django.db.models.ForeignKey.on_delete` argument to the
+ :class:`~django.db.models.ForeignKey`.
+
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
diff --git a/docs/releases/1.3.txt b/docs/releases/1.3.txt
index 7e843d90fd..addf849fbd 100644
--- a/docs/releases/1.3.txt
+++ b/docs/releases/1.3.txt
@@ -86,6 +86,19 @@ Users of Python 2.5 and above may now use :ref:`transaction management functions
For more information, see :ref:`transaction-management-functions`.
+Configurable delete-cascade
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+:class:`~django.db.models.ForeignKey` and
+:class:`~django.db.models.OneToOneField` now accept an
+:attr:`~django.db.models.ForeignKey.on_delete` argument to customize behavior
+when the referenced object is deleted. Previously, deletes were always
+cascaded; available alternatives now include set null, set default, set to any
+value, protect, or do nothing.
+
+For more information, see the :attr:`~django.db.models.ForeignKey.on_delete`
+documentation.
+
Contextual markers in translatable strings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index 4a927cc35e..7a59f6f634 100644
--- a/docs/topics/db/queries.txt
+++ b/docs/topics/db/queries.txt
@@ -749,15 +749,20 @@ model (e.g., by iterating over a ``QuerySet`` and calling ``delete()``
on each object individually) rather than using the bulk ``delete()``
method of a ``QuerySet``.
-When Django deletes an object, it emulates the behavior of the SQL
-constraint ``ON DELETE CASCADE`` -- in other words, any objects which
-had foreign keys pointing at the object to be deleted will be deleted
-along with it. For example::
+When Django deletes an object, by default it emulates the behavior of the SQL
+constraint ``ON DELETE CASCADE`` -- in other words, any objects which had
+foreign keys pointing at the object to be deleted will be deleted along with
+it. For example::
b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()
+.. versionadded:: 1.3
+ This cascade behavior is customizable via the
+ :attr:`~django.db.models.ForeignKey.on_delete` argument to the
+ :class:`~django.db.models.ForeignKey`.
+
Note that ``delete()`` is the only ``QuerySet`` method that is not exposed on a
``Manager`` itself. This is a safety mechanism to prevent you from accidentally
requesting ``Entry.objects.delete()``, and deleting *all* the entries. If you