Opened 19 months ago

Closed 19 months ago

Last modified 19 months ago

#29166 closed Bug (fixed)

in lookup doesn't work with lists in a When clause

Reported by: Matthew Pava Owned by: felixxm
Component: Database layer (models, ORM) Version: 2.0
Severity: Release blocker Keywords: lookup in
Cc: Дилян Палаузов Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Matthew Pava)

I have an annotation that worked fine in Django 1.11, but I just discovered that it doesn't work with Django 2.0. The error message reported:
TypeError: unhashable type: 'list'

I have an Order model that has a status and status_date field, and here's the query that worked in the past (simplified):

Order.objects.annotate(
    end_date=Case(
        When(
            status__in=[3, 2],
            then=Cast(F('status_date'), DateField())
        ),
        default=Value(timezone.now().date())
    )
)

Note the list used as the arg in the __in lookup.

My current workaround is to use Q objects with the | operator.

Order.objects.annotate(
    end_date=Case(
        When(
            Q(status=3) | Q(status=2),
            then=Cast(F('status_date'), DateField())
        ),
        default=Value(timezone.now().date())
    )
)

Others may not find that workaround as practical.
I have also not verified this issue in other Expressions in the ORM.

Change History (8)

comment:1 Changed 19 months ago by Matthew Pava

Description: modified (diff)

comment:2 Changed 19 months ago by felixxm

Owner: changed from nobody to felixxm
Severity: NormalRelease blocker
Status: newassigned
Triage Stage: UnreviewedAccepted

comment:3 Changed 19 months ago by felixxm

Has patch: set

comment:4 Changed 19 months ago by Carlton Gibson

Triage Stage: AcceptedReady for checkin

comment:5 Changed 19 months ago by GitHub <noreply@…>

Resolution: fixed
Status: assignedclosed

In 54f8043:

Fixed #29166 -- Fixed crash in When() expression with a list argument.

Thanks Matthew Pava for the report and Tim Graham and Carlton Gibson for
reviews.
Regression in 19b2dfd1bfe7fd716dd3d8bfa5f972070d83b42f.

comment:6 Changed 19 months ago by Mariusz Felisiak <felisiak.mariusz@…>

In 10a20e4:

[2.0.x] Fixed #29166 -- Fixed crash in When() expression with a list argument.

Thanks Matthew Pava for the report and Tim Graham and Carlton Gibson for
reviews.
Regression in 19b2dfd1bfe7fd716dd3d8bfa5f972070d83b42f.

Backport of 54f80430be4a9adf1fc00b4ca17547415fafc69b from master

comment:7 Changed 19 months ago by Дилян Палаузов

diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
+        return hash((path, output_field) + args + tuple([
+            (key, tuple(value)) if isinstance(value, list) else (key, value)
+            for key, value in kwargs.items()
+        ]))

Aren't here the [ and ] superflous, as the parameter of both tuple() and [] have to be iterable, and this the type of the inlined for:

>>> tuple([(x,y) for x, y in {'a': 1, 'b':2, 'c':3}.items()])
(('a', 1), ('b', 2), ('c', 3))
>>> tuple((x,y) for x, y in {'a': 1, 'b':2, 'c':3}.items())
(('a', 1), ('b', 2), ('c', 3))

comment:8 Changed 19 months ago by Дилян Палаузов

Cc: Дилян Палаузов added
Note: See TracTickets for help on using tickets.
Back to Top