﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
35945	Add async interface to Paginator	smiling-watermelon	wookkl	"If you provide a QuerySet into a paginator from an async context, the Paginator cannot retrieve `count` property of the QuerySet resulting in an error.
This can be avoided by making an async version of `page` method that would use an async version of `count` property that would refer to `acount` method of an object, if it exists.

As of now we have to use sync_to_async to run the pagination code in production.

Error traceback below:
{{{
(Partially omitted)
Traceback (most recent call last):
  File ""/app/MyProjectName/operations/XYZ/read.py"", line 23, in get_XYZ_model
    XYZ_list, total = await paginate_queryset(
                           ^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/MyProjectName/operations/utils/pagination.py"", line 12, in paginate_queryset
    page = paginator.page(qs)
               ^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/core/paginator.py"", line 89, in page
    number = self.validate_number(number)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/core/paginator.py"", line 70, in validate_number
    if number > self.num_pages:
                ^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/utils/functional.py"", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/core/paginator.py"", line 116, in num_pages
    if self.count == 0 and not self.allow_empty_first_page:
       ^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/utils/functional.py"", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/core/paginator.py"", line 110, in count
    return c()
           ^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/db/models/query.py"", line 620, in count
    return self.query.get_count(using=self.db)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/db/models/sql/query.py"", line 630, in get_count
    return obj.get_aggregation(using, {""__count"": Count(""*"")})[""__count""]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/db/models/sql/query.py"", line 616, in get_aggregation
    result = compiler.execute_sql(SINGLE)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/cachalot/monkey_patch.py"", line 37, in inner
    return original(compiler, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/cachalot/monkey_patch.py"", line 96, in inner
    return _get_result_or_execute_query(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/cachalot/monkey_patch.py"", line 64, in _get_result_or_execute_query
    result = execute_query_func()
             ^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/cachalot/monkey_patch.py"", line 80, in <lambda>
    execute_query_func = lambda: original(compiler, *args, **kwargs)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/db/models/sql/compiler.py"", line 1572, in execute_sql
    cursor = self.connection.cursor()
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/app/.venv/lib/python3.12/site-packages/django/utils/asyncio.py"", line 24, in inner
    raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
}}}

P.S. I'm 99.99% certain that cachalot is not at fault here at all, I can create a small repro-code example, if necessary.
P.P.S. I'm uncertain what type of issue this is. It's partially a feature request, partially a bug. I leave the decision on this matter to maintainers."	New feature	closed	Core (Other)	5.1	Normal	fixed	Paginator, async, SynchronousOnlyOperation	Jon Janzen	Ready for checkin	1	0	0	0	0	0
