Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30829 closed Bug (duplicate)

TypeError: can only concatenate tuple (not "list") to tuple

Reported by: Nahuel Owned by: nobody
Component: Database layer (models, ORM) Version: 2.1
Severity: Release blocker 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

Since release 2.1.13, using DRF, we got an exception filtering through a JSONField using a querystring. This doesn't happens using 2.1.12.

This seems related to the ticket : https://code.djangoproject.com/ticket/30769

Using pdb to see what contains lhs_params and rhs_params, show that the first is a tuple, and rhs_params is a list that contains an object of type JSONAdapter.

And there is the stacktrace:

  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/test.py", line 292, in get
    response = super(APIClient, self).get(path, data=data, **extra)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/test.py", line 209, in get
    return self.generic('GET', path, **r)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/test.py", line 238, in generic
    method, path, data, content_type, secure, **extra)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/test/client.py", line 422, in generic
    return self.request(**r)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/test.py", line 289, in request
    return super(APIClient, self).request(**kwargs)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/test.py", line 241, in request
    request = super(APIRequestFactory, self).request(**kwargs)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/test/client.py", line 503, in request
    raise exc_value
  File "/code/.tox/tests/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/viewsets.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/views.py", line 483, in dispatch
    response = self.handle_exception(exc)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/views.py", line 443, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/views.py", line 480, in dispatch
    response = handler(request, *args, **kwargs)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/mixins.py", line 42, in list
    page = self.paginate_queryset(queryset)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/generics.py", line 173, in paginate_queryset
    return self.paginator.paginate_queryset(queryset, self.request, view=self)
  File "/code/.tox/tests/lib/python3.6/site-packages/rest_framework/pagination.py", line 204, in paginate_queryset
    self.page = paginator.page(page_number)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/core/paginator.py", line 70, in page
    number = self.validate_number(number)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/core/paginator.py", line 48, in validate_number
    if number > self.num_pages:
  File "/code/.tox/tests/lib/python3.6/site-packages/django/utils/functional.py", line 80, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/core/paginator.py", line 97, in num_pages
    if self.count == 0 and not self.allow_empty_first_page:
  File "/code/.tox/tests/lib/python3.6/site-packages/django/utils/functional.py", line 80, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/core/paginator.py", line 91, in count
    return c()
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/query.py", line 392, in count
    return self.query.get_count(using=self.db)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/sql/query.py", line 504, in get_count
    number = obj.get_aggregation(using, ['__count'])['__count']
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/sql/query.py", line 472, in get_aggregation
    outer_query.add_subquery(inner_query, using)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/sql/subqueries.py", line 194, in add_subquery
    self.subquery, self.sub_params = query.get_compiler(using).as_sql(with_col_aliases=True)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 489, in as_sql
    where, w_params = self.compile(self.where) if self.where is not None else ("", [])
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 405, in compile
    sql, params = node.as_sql(self, self.connection)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/sql/where.py", line 81, in as_sql
    sql, params = compiler.compile(child)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 405, in compile
    sql, params = node.as_sql(self, self.connection)
  File "/code/.tox/tests/lib/python3.6/site-packages/django/contrib/postgres/lookups.py", line 11, in as_sql
    params = lhs_params + rhs_params
TypeError: can only concatenate tuple (not "list") to tuple

Change History (4)

comment:1 by Carlton Gibson, 5 years ago

Resolution: duplicate
Status: newclosed

Yes. Regression was introduced in 6c3dfba89215fc56fc27ef61829a6fff88be4abb. This is a duplicate of #30826, where we're tracking this. Will be resolved in v2.1.14.

comment:2 by Mariusz Felisiak, 5 years ago

Can you share your queryset (especially filters)? It would be great to collect more examples of this regression.

in reply to:  2 comment:3 by d-horner, 5 years ago

Replying to felixxm:

Can you share your queryset (especially filters)? It would be great to collect more examples of this regression.

Here's mine that are causing this issue:

    ....
    if request.POST.get("planfinder"):
        q = request.POST.get("planfinder")
        qs = PlanData.objects.filter(
            Q(service_areas__cities__icontains=q)
            | Q(service_areas__counties__icontains=q)
            | Q(service_areas__zipcodes__contains=q)
        )
        if qs.count() > 0:
            ....     

Calling .count() results in this traceback:

TypeError: can only concatenate tuple (not "list") to tuple
  File "django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "contextlib.py", line 74, in inner
    return func(*args, **kwds)
  File "planfinder/views.py", line 36, in plan_output
    if qs.count() > 0:
  File "django/db/models/query.py", line 392, in count
    return self.query.get_count(using=self.db)
  File "django/db/models/sql/query.py", line 504, in get_count
    number = obj.get_aggregation(using, ['__count'])['__count']
  File "django/db/models/sql/query.py", line 489, in get_aggregation
    result = compiler.execute_sql(SINGLE)
  File "django/db/models/sql/compiler.py", line 1087, in execute_sql
    sql, params = self.as_sql()
  File "django/db/models/sql/compiler.py", line 489, in as_sql
    where, w_params = self.compile(self.where) if self.where is not None else ("", [])
  File "django/db/models/sql/compiler.py", line 405, in compile
    sql, params = node.as_sql(self, self.connection)
  File "django/db/models/sql/where.py", line 81, in as_sql
    sql, params = compiler.compile(child)
  File "django/db/models/sql/compiler.py", line 405, in compile
    sql, params = node.as_sql(self, self.connection)
  File "django/db/models/sql/where.py", line 81, in as_sql
    sql, params = compiler.compile(child)
  File "django/db/models/sql/compiler.py", line 405, in compile
    sql, params = node.as_sql(self, self.connection)
  File "django/contrib/postgres/lookups.py", line 11, in as_sql
    params = lhs_params + rhs_params

I know .exists() is better practice, this was written quite some time ago!

Hope that helps.

Cheers!

comment:4 by Mariusz Felisiak, 5 years ago

Thanks we will add tests also for icontains.

Note: See TracTickets for help on using tickets.
Back to Top