Expression Comparison with Combinable

TL;DR: Allow us to do

queryset.annotate({
   "is_happy": F("expectations") > F("reality")
})

…and the rest of comparison operators (<, <=, >=, ==).


The Combinable class

Provide[s] the ability to combine one or two objects with some connector. For example F(‘foo’) + F(‘bar’).

However, it currently only allows arithmetic operators( + - * / ^ %) and bitwise operators (& | << >> #). Some people have expressed the desire to allow boolean comparison in here. There are workarounds to this, but they’re not neat (a. using ExpressionWrapper, b. using Case and When).

There is a small disadvantage that we have to declare the output field as a BooleanField, but we can include that in the code.

The code would look something like this:

class Combinable:
    ...
    GT = '>'

    def _bool_combine(self, other, connector):
        return ExpressionWrapper(
            self._combine(other, connector, False),
            output_field=models.BooleanField(),
        )

    def __gt__(self, other):
        return self._bool_combine(other, self.GT)

you could do it with what arguably is an extra step but …?

queryset.annotate(
    expectation=Value(10), # or actual field value
    reality=Value(5), # or actual field value
    is_happy=Case(
        When(
            expectation__gt=F('reality'),
            then=Value(True),
        ),
        default=Value(False),
        output_field=models.BooleanField()
    )
)

would that work?

Yes of course it’s possible but it looks a bit awkward. I was just wondering why they never put boolean comparisons in the first place since they’re so easy to implement. The only reason I can think of is that we’d have to place it on an expression wrapper to set the output field to boolean, which I did in my code. Is there any other reason not to have them?