4👍
Conditional expressions
One option for it is to use conditional expressions. They provide simple way of checking conditions and providing one of values depending on them. In your case it will look like:
sorted_things = things.annotate(diff=Case(When(n1=F('n2'), then=True), default=False, output_field=BooleanField())).order_by('diff')
Q and ExpressionWrapper
There is another, a bit hacky way, to achieve that by combining usage of Q
and ExpressionWrapper
.
In django, Q
is intended to be used inside filter()
, exclude()
, Case
etc. but it simply creates condition that apparently can be used anywhere. It has only one drawback: it doesn’t define what type is outputting (it’s always boolean and django can assume that in every case when Q
is intended to be used.
But there comes ExpressionWrapper
that allows you to wrap any expression and define it’s final output type. That way we can simply wrap Q
expression (or more than one Q
expresisons glued together using &
, |
and brackets) and define by hand what type it outputs.
Be aware that this is undocumented, so this behavior may change in future, but I’ve checked it using django versions 1.8, 1.11 and 2.0 and it works fine
Example:
sorted_things = things.annotate(diff=ExpressionWrapper(Q(n1=F('n2')), output_field=BooleanField())).order_by('diff')
2👍
You can work around it using Func() expressions.
from django.db.models import Func, F
class NotEqual(Func):
arg_joiner = '<>'
arity = 2
function = ''
things = Thing.objects.annotate(diff=NotEqual(F('n1'), F('n2'))).order_by('diff')
- [Django]-OSError: [Errno 30] Read-only file system in Django on Heroku
- [Django]-How to make Django use two different databases based on debug flag
- [Django]-Django – How to update a field inside a model save() method?
- [Django]-Django handler404 not called on raise Http404()