Skip to content

Commit b46643a

Browse files
seddonymtimgraham
authored andcommitted
[1.7.x] Refs #14645 -- Documented bug with exclude() and multi-value relations
Backport of 6770b7e from master
1 parent 5cad259 commit b46643a

File tree

1 file changed

+29
-10
lines changed

1 file changed

+29
-10
lines changed

docs/topics/db/queries.txt

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,7 @@ find entries linked to tags called *"music"* and *"bands"* or we might want an
545545
entry that contains a tag with a name of *"music"* and a status of *"public"*.
546546

547547
To handle both of these situations, Django has a consistent way of processing
548-
:meth:`~django.db.models.query.QuerySet.filter` and
549-
:meth:`~django.db.models.query.QuerySet.exclude` calls. Everything inside a
548+
:meth:`~django.db.models.query.QuerySet.filter` calls. Everything inside a
550549
single :meth:`~django.db.models.query.QuerySet.filter` call is applied
551550
simultaneously to filter out items matching all those requirements. Successive
552551
:meth:`~django.db.models.query.QuerySet.filter` calls further restrict the set
@@ -580,14 +579,34 @@ that were published in 2008. The entries selected by the second filter may or
580579
may not be the same as the entries in the first filter. We are filtering the
581580
``Blog`` items with each filter statement, not the ``Entry`` items.
582581

583-
All of this behavior also applies to
584-
:meth:`~django.db.models.query.QuerySet.exclude`: all the conditions in a
585-
single :meth:`~django.db.models.query.QuerySet.exclude` statement apply to a
586-
single instance (if those conditions are talking about the same multi-valued
587-
relation). Conditions in subsequent
588-
:meth:`~django.db.models.query.QuerySet.filter` or
589-
:meth:`~django.db.models.query.QuerySet.exclude` calls that refer to the same
590-
relation may end up filtering on different linked objects.
582+
.. note::
583+
584+
The behavior of :meth:`~django.db.models.query.QuerySet.filter` for queries
585+
that span multi-value relationships, as described above, is not implemented
586+
equivalently for :meth:`~django.db.models.query.QuerySet.exclude`. Instead,
587+
the conditions in a single :meth:`~django.db.models.query.QuerySet.exclude`
588+
call will not necessarily refer to the same item.
589+
590+
For example, the following query would exclude blogs that contain *both*
591+
entries with *"Lennon"* in the headline *and* entries published in 2008::
592+
593+
Blog.objects.exclude(
594+
entry__headline__contains='Lennon',
595+
entry__pub_date__year=2008,
596+
)
597+
598+
However, unlike the behavior when using
599+
:meth:`~django.db.models.query.QuerySet.filter`, this will not limit blogs
600+
based on entries that satisfying both conditions. In order to do that, i.e.
601+
to select all blogs that do not contain entries published with *"Lennon"*
602+
that were published in 2008, you need to make two queries::
603+
604+
Blog.objects.exclude(
605+
entry=Entry.objects.filter(
606+
headline__contains='Lennon',
607+
pub_date__year=2008,
608+
),
609+
)
591610

592611
.. _using-f-expressions-in-filters:
593612

0 commit comments

Comments
 (0)