In Django model QuerySets, I see that there is a
__lt for comparative values, but is there a
!= (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)
!= is not correct syntax. I also tried
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
exclude methods available so you can always just switch the logic around to get the desired result.
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
There are three options:
results = Model.objects.exclude(a=True).filter(x=5)
from 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)
While you can filter Models with
__lte, you cannot use
!=. However, you can achieve better filtering using the Q object.
You can avoid chaining
QuerySet.exclude(), and use this:
from django.db.models import Q object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
Pending design decision. Meanwhile, use
The Django issue tracker has the remarkable entry #5763,
titled “Queryset doesn’t have a “not equal” filter operator”.
It is remarkable because (as of April 2016) it was
“opened 9 years ago” (in the Django stone age),
“closed 4 years ago”, and
“last changed 5 months ago”.
Read through the discussion, it is interesting.
Basically, some people argue
__ne should be added
while others say
exclude() is clearer and hence
should not be added.
(I agree with the former, because the latter argument is
roughly equivalent to saying Python should not have
Using exclude and filter
results = Model.objects.filter(x=5).exclude(a=true)
You should use
exclude like this
results = Model.objects.exclude(a=true).filter(x=5)
This will give your desired result.
from django.db.models import Q results = Model.objects.exclude(Q(a=True) & ~Q(x=5))
for not equal you can use
~ on an equal query. obviously,
Q can be used to reach the equal query.
The last bit of code will exclude all objects where x!=5 and a is True. Try this:
results = Model.objects.filter(a=False, x=5)
Remember, the = sign in the above line is assigning False to the parameter a and the number 5 to the parameter x. It’s not checking for equality. Thus, there isn’t really any way to use the != symbol in a query call.
What you are looking for are all objects that have either
x=5. In Django,
| serves as
OR operator between querysets:
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
results = Model.objects.filter(a = True).exclude(x = 5)
Generetes this sql:
select * from tablex where a != 0 and x !=5
The sql depends on how your True/False field is represented, and the database engine. The django code is all you need though.
Watch out for lots of incorrect answers to this question!
Gerard’s logic is correct, though it will return a list rather than a queryset (which might not matter).
If you need a queryset, use Q:
from django.db.models import Q results = Model.objects.filter(Q(a=false) | Q(x=5))
If we need to exclude/negate based on the sub queryset we can use,
When a conditional expression returns a boolean value, it is possible to use it directly in filters. Here
non_unique_account_type returns a boolean value. But, still, we can use it in the filter.
>>> non_unique_account_type = Client.objects.filter( ... account_type=OuterRef('account_type'), ... ).exclude(pk=OuterRef('pk')).values('pk') >>> Client.objects.filter(~Exists(non_unique_account_type))
In the SQL terms, it evaluates to:
SELECT * FROM client c0 WHERE NOT EXISTS ( SELECT c1.id FROM client c1 WHERE c1.account_type = c0.account_type AND NOT c1.id = c0.id )