浏览代码

Refs #14645 -- Documented bug with exclude() and multi-value relations

David Seddon 10 年之前
父节点
当前提交
6770b7ecd2
共有 1 个文件被更改,包括 29 次插入10 次删除
  1. 29 10
      docs/topics/db/queries.txt

+ 29 - 10
docs/topics/db/queries.txt

@@ -546,8 +546,7 @@ find entries linked to tags called *"music"* and *"bands"* or we might want an
 entry that contains a tag with a name of *"music"* and a status of *"public"*.
 
 To handle both of these situations, Django has a consistent way of processing
-:meth:`~django.db.models.query.QuerySet.filter` and
-:meth:`~django.db.models.query.QuerySet.exclude` calls. Everything inside a
+:meth:`~django.db.models.query.QuerySet.filter` calls. Everything inside a
 single :meth:`~django.db.models.query.QuerySet.filter` call is applied
 simultaneously to filter out items matching all those requirements. Successive
 :meth:`~django.db.models.query.QuerySet.filter` calls further restrict the set
@@ -581,14 +580,34 @@ that were published in 2008. The entries selected by the second filter may or
 may not be the same as the entries in the first filter. We are filtering the
 ``Blog`` items with each filter statement, not the ``Entry`` items.
 
-All of this behavior also applies to
-:meth:`~django.db.models.query.QuerySet.exclude`: all the conditions in a
-single :meth:`~django.db.models.query.QuerySet.exclude` statement apply to a
-single instance (if those conditions are talking about the same multi-valued
-relation). Conditions in subsequent
-:meth:`~django.db.models.query.QuerySet.filter` or
-:meth:`~django.db.models.query.QuerySet.exclude` calls that refer to the same
-relation may end up filtering on different linked objects.
+.. note::
+
+    The behavior of :meth:`~django.db.models.query.QuerySet.filter` for queries
+    that span multi-value relationships, as described above, is not implemented
+    equivalently for :meth:`~django.db.models.query.QuerySet.exclude`. Instead,
+    the conditions in a single :meth:`~django.db.models.query.QuerySet.exclude`
+    call will not necessarily refer to the same item.
+
+    For example, the following query would exclude blogs that contain *both*
+    entries with *"Lennon"* in the headline *and* entries published in 2008::
+
+        Blog.objects.exclude(
+            entry__headline__contains='Lennon',
+            entry__pub_date__year=2008,
+        )
+
+    However, unlike the behavior when using
+    :meth:`~django.db.models.query.QuerySet.filter`, this will not limit blogs
+    based on entries that satisfying both conditions. In order to do that, i.e.
+    to select all blogs that do not contain entries published with *"Lennon"*
+    that were published in 2008, you need to make two queries::
+
+        Blog.objects.exclude(
+            entry=Entry.objects.filter(
+                headline__contains='Lennon',
+                pub_date__year=2008,
+            ),
+        )
 
 .. _using-f-expressions-in-filters: