#29643 closed Bug (fixed)
Hashing list in Q objects when using __in lookup
Reported by: | rhyre | Owned by: | Mariusz Felisiak |
---|---|---|---|
Component: | Utilities | Version: | 2.0 |
Severity: | Release blocker | Keywords: | hash, tuple, list, drf |
Cc: | Mariusz Felisiak | 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 )
When using djangorestframework with django 2.0.X with lookup _in like id__in=[1,2,3]
will raise: unhashable type: 'list'
traceback ends to this file:
/django/utils/tree.py" in __hash__ 74. return hash((self.__class__, self.connector, self.negated) + tuple(self.children))
When using tuples with __in
everything works fine. But when using .values_list() on query I need to use tuple(query) to use it in Q object with __in
lookup.
Code worked before with 1.11 version just fine. Also when using _in without Q() everything seems to work just fine.
Change History (14)
comment:1 by , 6 years ago
Description: | modified (diff) |
---|
comment:2 by , 6 years ago
comment:3 by , 6 years ago
Model.objects.prefetch_related('types').exclude(status=1).annotate( category=Case( When(Q(status__in=[1,2,3]) & Q(id__in=[1,2,3]), then=Value(2)), default=Value(1), output_field=IntegerField() ) ).only('category')
then it is used in viewsets.ReadOnlyModelViewSet of rest framework in get_queryset.
When using
When(status__in=[1,2,3], id__in=[1,2,3], then=Value(2)),
everything works fine. Also when using Q with tuple as:
When(Q(status__in=(1,2,3)) & Q(id__in=(1,2,3)), then=Value(2)),
its ok.
Only with list it will crash. I've workarounded this to not use Q but it wasn't a problem before.
Without DRF it seems to work just fine. There is a problem with serialization. As it was working before I think its an issue on Django side.
comment:4 by , 6 years ago
Hi. Thanks for the follow-up.
This still isn’t really a minimal reproduce.
Can you provide a test-case that demonstrates the issue? Or a small project?
Any chance you could use git bisect to identify the commit which broke your usage?
Without DRF it seems to work just fine. There is a problem with serialization
What exactly do you mean here? It’s not quite clear. (Do you mean that the ORM call works fine until embedded with the DRF request-response handling? If so you’ll need to provide a sample project I think…(?))
Could you paste the entire traceback for the error?
follow-up: 6 comment:5 by , 6 years ago
Cc: | added |
---|
It is probably a regression introduced by fc6528b25ab1834be1a478b405bf8f7ec5cf860c (#28629).
comment:6 by , 6 years ago
Replying to felixxm:
It is probably a regression introduced by regression fix (see https://github.com/django/django/commit/fc6528b25ab1834be1a478b405bf8f7ec5cf860c).
In 2.0.8 still not working. Haven't tried 2.1 yet. Too much to refactor to use 2.1.
I'll try to create a demo when I'll have some time.
comment:7 by , 6 years ago
Severity: | Normal → Release blocker |
---|---|
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → Bug |
Crash can be reproduce at the Node
level with hash(Node([['a', 1], ['b', 2]]))
.
comment:8 by , 6 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:9 by , 6 years ago
Full traceback:
File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner 35. response = get_response(request) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response 128. response = self.process_exception_by_middleware(e, request) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response 126. response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view 54. return view_func(*args, **kwargs) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/rest_framework/viewsets.py" in view 95. return self.dispatch(request, *args, **kwargs) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/rest_framework/views.py" in dispatch 494. response = self.handle_exception(exc) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/rest_framework/views.py" in handle_exception 454. self.raise_uncaught_exception(exc) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/rest_framework/views.py" in dispatch 491. response = handler(request, *args, **kwargs) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/rest_framework/mixins.py" in list 40. queryset = self.filter_queryset(self.get_queryset()) File "/home/rhyre/-/testline_rest.py" in get_queryset 109. return LegacyTestlineService.list_testlines() File "/home/rhyre/-/testline.py" in list_testlines 162. return cache_query(key='testline/list', func=query, args=['id', 'name', 'status', 'add_date'], timeout=600) File "/home/rhyre/-/cache.py" in cache_query 40. cache.set(key, dill.dumps(result), timeout) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/dill/_dill.py" in dumps 293. dump(obj, file, protocol, byref, fmode, recurse)#, strictio) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/dill/_dill.py" in dump 286. pik.dump(obj) File "/usr/lib64/python3.6/pickle.py" in dump 409. self.save(obj) File "/usr/lib64/python3.6/pickle.py" in save 496. rv = reduce(self.proto) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/query.py" in __getstate__ 224. self._fetch_all() File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/query.py" in _fetch_all 1179. self._result_cache = list(self._iterable_class(self)) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/query.py" in __iter__ 53. results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in execute_sql 1055. sql, params = self.as_sql() File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in as_sql 448. extra_select, order_by, group_by = self.pre_sql_setup() File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in pre_sql_setup 55. group_by = self.get_group_by(self.select + extra_select, order_by) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in get_group_by 129. expressions = self.collapse_group_by(expressions, having_group_by) File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in collapse_group_by 180. expr for expr in expressions if expr in pks or getattr(expr, 'alias', None) not in aliases File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in <listcomp> 180. expr for expr in expressions if expr in pks or getattr(expr, 'alias', None) not in aliases File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/expressions.py" in __hash__ 390. for key, value in kwargs.items() File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/db/models/expressions.py" in __hash__ 390. for key, value in kwargs.items() File "/home/rhyre/.virtualenvs/py3new/lib/python3.6/site-packages/django/utils/tree.py" in __hash__ 74. return hash((self.__class__, self.connector, self.negated) + tuple(self.children)) Exception Type: TypeError at /testline/list/ajax Exception Value: unhashable type: 'list' Request information: USER: AnonymousUser
comment:11 by , 6 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Please include a minimal example to reproduce the crash. My guess of
Model.objects.filter(Q(id__in=[1,2,3]))
didn't crash. Thanks.