#25107: Inconsistent results when combining Q objects filtering on m2m fields
----------------------------------------------+--------------------
Reporter: AlexHill | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.8
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------
Say you have a model `Number` representing positive integers and a
`Category` model representing categories of numbers, associated through a
many-to-many field `Number.tags`.
Say you want to get numbers that are odd but aren't prime. The first query
below produces what you want, the second doesn't. I've cut down the SQL to
the relevant bits.
The correct query and SQL:
`Number.objects.filter(Q(tags__tag='odd')).filter(~Q(tags__tag='prime').distinct()`
{{{#!python
SELECT DISTINCT number.id
FROM number
INNER JOIN number_tags ON number.id = number_tags.number_id
INNER JOIN category ON number_tags.category_id = category.id
WHERE category.tag = 'odd'
AND NOT number.id IN (SELECT U1.number_id
FROM number_tags U1
INNER JOIN category U2 ON U1.category_id =
U2.id
WHERE U2.tag = 'prime')
}}}
Here's the wrong one. This yields odd numbers, without filtering out
primes.
`Number.objects.filter(Q(tags__tag='odd') &
~Q(tags__tag='prime')).distinct()`
{{{#!python
SELECT DISTINCT number.id
FROM number
INNER JOIN number_tags ON number.id = number_tags.number_id
INNER JOIN category ON number_tags.category_id = category.id
WHERE category.tag = 'odd'
AND NOT number.id IN (SELECT U1.number_id
FROM number_tags U1
INNER JOIN category U2 ON U1.category_id =
U2.id
WHERE U2.tag = 'prime' AND U1.id =
number_tags.id)
}}}
The only difference is the extra `U1.id = number_tags.id` in the WHERE
clause, which basically means rather than looking for ''numbers'' that are
"odd" and also "not prime", you're looking for ''tags'' meeting those
criteria, means the "not prime" has no effect.
Haven't dived into the ORM to see what's going on here yet, just wanted to
get this down.
--
Ticket URL: <https://code.djangoproject.com/ticket/25107>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.717191a07519acea6c588b960e120792%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.