In my Django 1.9 project I am trying to output something like this:
return MyModel.objects.values(...).\
annotate(flg = ExpressionWrapper(F('rgt') - F('lft') > 0,
output_field = BooleanField()))
This yields AttributeError: 'bool' object has no attribute 'resolve_expression'
error.
I try to rewrite it using Case-when
syntax:
return MyModel.objects.values(...)\
.annotate(flg = Case(When(F('rgt') - F('lft') > 0, then = True,
output_field = BooleanField())))
This time, I end up with TypeError: __init__() takes either a Q object or lookups as keyword arguments
error. I am lost. Any ideas ?
Try:
from django.db.models import Q, F
...
return MyModel.objects.values(...).\
annotate(flg=ExpressionWrapper(Q(rgt=F('lft')),
output_field=BooleanField()))
Feature request to make it easier: https://code.djangoproject.com/ticket/27021
Django expressions don't support the comparison operators using standard syntax.
Check https://docs.djangoproject.com/en/stable/ref/models/expressions/#supported-arithmetic
However, you can use Func()
expressions: https://docs.djangoproject.com/en/stable/ref/models/expressions/#func-expressions
.annotate(flg=Func(F('rgt') + F('lft'), template='%(expressions)s > 0'))
Or even better, define a Function / Transform class:
class GreaterThanZero(Transform):
template = '%(expressions)s > 0'
.annotate(flg=GreaterThanZero(F('rgt') + F('lft')))
Transforms are unary operators, extending Transform
you can ensure that only one expression
is passed as an argument. So that you couldn't do GreaterThanZero(F('rgt') + F('lft'), 1, 2, 3, 14)
.
Obviously, a more flexible solution should allow to pass both sides of the comparison. Somethin like this:
class GreaterThan(Func):
arg_joiner = '<'
arity = 2
function = ''
.annotate(flg=GreaterThan(F('rgt') + F('lft'), 0))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With