Opened 2 years ago

Closed 2 years ago

#33635 closed Bug (invalid)

Django 3.2.13 raises ProgrammingError "can't adapt type 'LessThan'"

Reported by: Shaheed Haque Owned by: nobody
Component: Database layer (models, ORM) Version: 3.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I'm using Postgres as my db engine. I have a couple of lines of code like this:

qs = company.employee_set.annotate(past=Coalesce(LessThan(F('end_date'), Value(date.today())), Value(False)))
qs = qs.order_by(...)
return list(qs.values_list(...))

The idea is to compare "end_date" (a DateField which can be null) with the given Python datetime.date, i.e. in Python terms, something like this:

past = end_date < today if end_date is not None else False

This works as I expected on Django 4.0.4, but fails on 3.2.13 where is causes the can't adapt type 'LessThan'. I tried a couple of other formulations of the query, including moving the Coalesce to "inside":

...annotate(past=LessThan(Coalesce(F('end_date'), Value('1999-01-01'), output_field=DateField()), Value(date.today())))

This also worked on Django 4.0.4, but failed on 3.2.13 with TypeError "QuerySet.annotate() received non-expression(s): <django.db.models.lookups.LessThan object at ...>."

Since a Lookup is a query expression, I assume this is a bug? Is there a workaround I might try?

Change History (1)

comment:1 by Mariusz Felisiak, 2 years ago

Resolution: invalid
Status: newclosed

Django 3.2 is in extended support and doesn't receive bugfixes (except security patches) anymore. You can use Case() on Django 3.2:

.annotate(past=Case(
    When(Q(end_date__lt=date.today()), then=True),
    default=False,
    output_field=BooleanField(),
))

or ExpressionWrapper():

.annotate(past=ExpressionWrapper(
    Q(end_date__lt=date.today()),
    output_field=BooleanField(),
))
Note: See TracTickets for help on using tickets.
Back to Top