Opened 13 years ago

Closed 4 years ago

Last modified 4 years ago

#16893 closed Bug (wontfix)

negation of Q object returns the same thing

Reported by: morgy.wahl@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Aymeric Augustin)

Not sure if this is a bug.

I was attempt to construct a Q object that wouldn't ever match anything (an API calls for a Q object to be returned, but certain situations call for nothing to be matched by it). I initially figured ~ Q() would do the trick, but that matches everything, just like a plain Q().

(I ended up using Q(pk__isnull=True), which is a hack but seems to be OK.)

Change History (7)

comment:1 by Aymeric Augustin, 13 years ago

Description: modified (diff)

Fixed formatting (you can use "preview" before submitting a ticket).

comment:3 by Carl Meyer, 13 years ago

Triage Stage: UnreviewedAccepted

Haven't dug into what would be required to make this work, but presuming it can be reasonably implemented this seems sensible.

comment:4 by Baptiste Mispelon, 8 years ago

For reference, it seems that the current behavior is tested (if not documented): https://github.com/django/django/blob/master/tests/queries/tests.py#L1692-L1694

Come to think of it, I'm not really sure how empty Q objects should be treated: what's the expected result of filter(Q()), filter(~Q()), exclude(Q()), or exclude(~Q())?

comment:5 by Morgan Wahl, 8 years ago

Ah, I see. filter() == all() == exclude(), all of which != none(). Keeping filter(~Q(...)) == exclude(Q(...))) certainly makes sense (if that's possible).

Maybe define a special singleton instance of Q that matches nothing?

comment:6 by Morgan Wahl, 8 years ago

To elaborate:

In django.db.models or someplace like it:

Nope = Q(pk__isnull=True)

Then in other code:

from django.db.models import Nope
qs.filter(Nope) == qs.none()
qs.exclude(Nope) == qs.all()

That still uses my pk__isnull=True hack, but that might be fine. Alternatively, the Q class itself could add some kind of explicit support for this.

I think these expressions should all be true: Nope | Q() == Q(), Nope & Q() == Nope, ~Nope == Q()

Nope isn't a great name, but it was the best I could do; Null is confusing with the SQL concept, None is taken, of course, and Nothing sounds like what filter(Nope) would return, not what it's passed. Is there a better word for unmatchable criteria?

comment:7 by Mariusz Felisiak, 4 years ago

Resolution: wontfix
Status: newclosed

As mentioned by Baptiste, the current behavior is tested and expected (IMO). Filtering by an empty condition Q() and negation of an empty condition ~Q() should return all objects, because negation of an empty condition is still an empty condition.

You can start a discussion on DevelopersMailingList if you don't agree.

comment:8 by Mariusz Felisiak, 4 years ago

Triage Stage: AcceptedUnreviewed
Note: See TracTickets for help on using tickets.
Back to Top