#29166 closed Bug (fixed)
in lookup doesn't work with lists in a When clause
| Reported by: | Matthew Pava | Owned by: | Mariusz Felisiak |
|---|---|---|---|
| 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 )
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 by , 8 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 8 years ago
| Owner: | changed from to |
|---|---|
| Severity: | Normal → Release blocker |
| Status: | new → assigned |
| Triage Stage: | Unreviewed → Accepted |
comment:4 by , 8 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
comment:7 by , 8 years ago
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 by , 8 years ago
| Cc: | added |
|---|
Regression in 19b2dfd1bfe7fd716dd3d8bfa5f972070d83b42f.