Opened 8 years ago
Closed 7 years ago
#29009 closed Bug (needsinfo)
Error using jsonpickle.encode() on a QuerySet with a Subquery: "This queryset contains a reference to an outer query and may only be used in a subquery"
| Reported by: | Vasiliy Maryutenkov | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 2.0 |
| 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
Hello
I've tried to serialize queryset with Subquery object and it failed with that error.
"This queryset contains a reference to an outer query and may only be used in a subquery"
subquery = Transaction.objects.filter(user=OuterRef('pk')).values('user').order_by('user').annotate(txs=Count('*')).annotate(txs_value=Sum(F('tx_value')*F('symbol__price_in_eth'))).annotate(txs_value_eur=Sum((F('tx_value')*F('symbol__price_in_eth'))/eur.price_in_eth))
investors_qs = User.objects.filter(ether_wallet__isnull=False).annotate(txs=Subquery(subquery.values('txs')[:1])).annotate(txs_value=Subquery(subquery.values('txs_value')[:1])).annotate(txs_value_eur=Subquery(subquery.values('txs_value_eur')[:1]))
jsonpickle.encode(investors_qs.query)
'This queryset contains a reference to an outer query and may '
ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.
is it normal behaviour or a bug?
Change History (5)
comment:1 by , 8 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
| Summary: | This queryset contains a reference to an outer query and may only be used in a subquery → Error using jsonpickle.encode() on a QuerySet with a Subquery: "This queryset contains a reference to an outer query and may only be used in a subquery" |
comment:2 by , 7 years ago
I was also trying to cache a Queryset that has a Subquery and an OuterRef, and am getting the same error.
Using Redis as a caching backend. I also tried to directly pickle the queryset with python's pickle and I get the same error. Also tried caching qs.query, same issue.
qs = self.queryset.filter(
Q(user__in=Follow.objects.filter(
follower=userid,
).values('followee')) \
| Q(user=userid))\
.prefetch_related('postlike_set')\
.annotate(Count('postlike'))\
.annotate(Count('postcomment'))\
.annotate(
liked=Subquery(
PostLike.objects.filter(user=self.request.user,
post_id=OuterRef('id'),
).values('user')
)
)
cache.set(f'feed:{userid}', qs)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django_redis/client/default.py", line 326, in encode
value = self._serializer.dumps(value)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django_redis/serializers/pickle.py", line 32, in dumps
return pickle.dumps(value, self._pickle_version)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/query.py", line 224, in __getstate__
self._fetch_all()
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/query.py", line 1179, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/query.py", line 107, in __iter__
for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1014, in results_iter
results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1050, in execute_sql
sql, params = self.as_sql()
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 458, in as_sql
where, w_params = self.compile(self.where) if self.where is not None else ("", [])
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 390, in compile
sql, params = node.as_sql(self, self.connection)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/sql/where.py", line 80, in as_sql
sql, params = compiler.compile(child)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 390, in compile
sql, params = node.as_sql(self, self.connection)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 130, in as_sql
return super().as_sql(compiler, connection)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/lookups.py", line 161, in as_sql
rhs_sql, rhs_params = self.process_rhs(compiler, connection)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/lookups.py", line 260, in process_rhs
return super().process_rhs(compiler, connection)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/lookups.py", line 90, in process_rhs
sql, params = compiler.compile(value)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 390, in compile
sql, params = node.as_sql(self, self.connection)
File "/Users/my-app/app/venv-app/lib/python3.6/site-packages/django/db/models/expressions.py", line 536, in as_sql
'This queryset contains a reference to an outer query and may '
ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.
comment:3 by , 7 years ago
| Resolution: | invalid |
|---|---|
| Status: | closed → new |
I'd like to reopen this ticket as this is isn't related to usage of third party but seems to be caused by Django itself.
comment:4 by , 7 years ago
Does the error only happen when pickling the queryset? Can you explain why Django is at fault? Is the error message incorrect?
comment:5 by , 7 years ago
| Resolution: | → needsinfo |
|---|---|
| Status: | new → closed |
| Type: | Uncategorized → Bug |
I'm not sure how
jsonpickle.encode()works but if it's trying to evaluateinvestors_qs.query, as a string, then I see that the exception raised is in the path that generates the SQL. In general, "is it a bug?" questions should go to our support channels. See TicketClosingReasons/UseSupportChannels.