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