#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 Expression
s in the ORM.
Change History (8)
comment:1 by , 7 years ago
Description: | modified (diff) |
---|
comment:2 by , 7 years ago
Owner: | changed from | to
---|---|
Severity: | Normal → Release blocker |
Status: | new → assigned |
Triage Stage: | Unreviewed → Accepted |
comment:4 by , 7 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:7 by , 7 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 , 7 years ago
Cc: | added |
---|
Regression in 19b2dfd1bfe7fd716dd3d8bfa5f972070d83b42f.