How do I do a not equal in Django queryset filtering?
In Django model QuerySets, I see that there is a __gt
and __lt
for comparative values, but is there a __ne
or !=
(not equals)? I want to filter out using a not equals. For example, for
Model:
bool a;
int x;
I want to do
results = Model.objects.exclude(a=True, x!=5)
The !=
is not correct syntax. I also tried __ne
.
I ended up using:
results = Model.objects.exclude(a=True, x__lt=5).exclude(a=True, x__gt=5)
You can use Q objects for this. They can be negated with the ~
operator and combined much like normal Python expressions:
from myapp.models import Entry
from django.db.models import Q
Entry.objects.filter(~Q(id=3))
will return all entries except the one(s) with 3
as their ID:
[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]
Your query appears to have a double negative, you want to exclude all rows where x
is not 5, so in other words you want to include all rows where x
is 5. I believe this will do the trick:
results = Model.objects.filter(x=5).exclude(a=True)
To answer your specific question, there is no "not equal to" field lookup but that's probably because Django has both filter
and exclude
methods available so you can always just switch the logic around to get the desired result.
the field=value
syntax in queries is a shorthand for field__exact=value
. That is to say that Django puts query operators on query fields in the identifiers. Django supports the following operators:
exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
date
year
iso_year
month
day
week
week_day
iso_week_day
quarter
time
hour
minute
second
isnull
regex
iregex
I'm sure by combining these with the Q objects as Dave Vogt suggests and using filter()
or exclude()
as Jason Baker suggests you'll get exactly what you need for just about any possible query.
There are three options:
-
Chain
exclude
andfilter
results = Model.objects.exclude(a=True).filter(x=5)
-
Use
Q()
objects and the~
operatorfrom django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5)
-
Register a custom lookup function
from django.db.models import Lookup from django.db.models import Field @Field.register_lookup class NotEqual(Lookup): lookup_name = 'ne' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) params = lhs_params + rhs_params return '%s <> %s' % (lhs, rhs), params
Which can the be used as usual:
results = Model.objects.exclude(a=True, x__ne=5)
It's easy to create a custom lookup, there's an __ne
lookup example in Django's official documentation.
You need to create the lookup itself first:
from django.db.models import Lookup
class NotEqual(Lookup):
lookup_name = 'ne'
def as_sql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return '%s <> %s' % (lhs, rhs), params
Then you need to register it:
from django.db.models import Field
Field.register_lookup(NotEqual)
And now you can use the __ne
lookup in your queries like this:
results = Model.objects.exclude(a=True, x__ne=5)