question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] TypeError: 'coroutine' object is not subscriptable

See original GitHub issue
async def search(request, keywords: str):
    item = await sync_to_async(list)(Movie.objects.all())

    if item:
        return item

Error code after running

Traceback (most recent call last):
  File "D:\Program Files (x86)\Anaconda3\envs\django\lib\site-packages\ninja\operation.py", line 99, in run
    result = self.view_func(request, **values)
  File "D:\Program Files (x86)\Anaconda3\envs\django\lib\site-packages\ninja\pagination.py", line 145, in view_with_pagination
    result = paginator.paginate_queryset(
  File "D:\Program Files (x86)\Anaconda3\envs\django\lib\site-packages\ninja\pagination.py", line 69, in paginate_queryset
    "items": queryset[offset : offset + limit],
TypeError: 'coroutine' object is not subscriptable

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
chrismaillecommented, Nov 29, 2022

@sunboy123 sure, I’ve created a async version for the decorator. Here is the code:

import inspect
from functools import partial, wraps
from typing import Any, Callable, Tuple, Type

from asgiref.sync import sync_to_async
from django.db.models import QuerySet
from ninja.constants import NOT_SET
from ninja.pagination import LimitOffsetPagination, PaginationBase, make_response_paginated
from ninja.types import DictStrAny


class AsyncLimitOffsetPagination(LimitOffsetPagination):
    async def paginate_queryset(
        self,
        queryset: QuerySet,
        pagination: LimitOffsetPagination.Input,
        **params: DictStrAny,
    ):
        offset = pagination.offset
        limit: int = pagination.limit

        @sync_to_async
        def process_query_set():
            return {
                "items": queryset[offset : offset + limit] if queryset else [],
                "count": self._items_count(queryset) if queryset else 0,
            }

        return await process_query_set()


def apaginate(func_or_pgn_class: Any = NOT_SET, **paginator_params: DictStrAny) -> Callable:

    isfunction = inspect.isfunction(func_or_pgn_class)
    isnotset = func_or_pgn_class == NOT_SET

    pagination_class: Type[PaginationBase] = AsyncLimitOffsetPagination

    if isfunction:
        return _inject_pagination(func_or_pgn_class, pagination_class)

    if not isnotset:
        pagination_class = func_or_pgn_class

    async def wrapper(func: Callable) -> Any:
        return await _inject_pagination(func, pagination_class, **paginator_params)

    return wrapper


def _inject_pagination(
    func: Callable,
    paginator_class: Type[PaginationBase],
    **paginator_params: Any,
) -> Callable:
    paginator: PaginationBase = paginator_class(**paginator_params)

    @wraps(func)
    async def view_with_pagination(*args: Tuple[Any], **kwargs: DictStrAny) -> Any:
        pagination_params = kwargs.pop("ninja_pagination")
        if paginator.pass_parameter:
            kwargs[paginator.pass_parameter] = pagination_params

        items = await func(*args, **kwargs)

        result = await paginator.paginate_queryset(items, pagination=pagination_params, **kwargs)
        if paginator.Output:
            result[paginator.items_attribute] = list(result[paginator.items_attribute])
            # ^ forcing queryset evaluation #TODO: check why pydantic did not do it here
        return result

    view_with_pagination._ninja_contribute_args = [  # type: ignore
        (
            "ninja_pagination",
            paginator.Input,
            paginator.InputSource,
        ),
    ]

    if paginator.Output:
        view_with_pagination._ninja_contribute_to_operation = partial(  # type: ignore
            make_response_paginated,
            paginator,
        )

    return view_with_pagination

An example:

from django.http import HttpRequest
from django.db import models, QuerySet
from ninja import NinjaAPI, ModelSchema

class MyModel(models.Model):
   foo = models.CharField(max_length=255)
   is_active = models.BooleanField(default=True)

class MyModelOut(ModelSchema):
  class Meta:
     model = MyModel
     model_fields = ["foo"]


api= NinjaAPI()

@api.get("/my-model", response=list[MyModelOut])
@apaginate
async def list_model(request: HttpRequest) -> QuerySet[MyModel]:
    return MyModel.objects.filter(is_active=True)

Please note, with this solution, if you need to use another Pagination class (like AsyncLimitOffsetPagination) you need to make that async compatible too.

0reactions
sunboy123commented, Dec 2, 2022

@chrismaille thanks a lot .

Read more comments on GitHub >

github_iconTop Results From Across the Web

python: TypeError: 'coroutine' object is not subscriptable
basically the awaitable returns a (nested) dict and you can retrieve the values from the dict once the await is completed: (await function())...
Read more >
TypeError: 'coroutine' object is not subscriptable #825 - GitHub
I get the error TypeError: 'coroutine' object is not subscriptable when I try to read a CSV from S3. It does not occur...
Read more >
Nbdev_test_nbs in CI:TypeError: 'coroutine' object is not ...
I only pin to nbconvert==5 , I have jupyter_client= 6.1. 12 and all works fine. (Over-pinning should be avoided like the plague, creates...
Read more >
tiangolo/fastapi - Gitter
I'm getting this error: ValueError: [KeyError(<class 'coroutine'>), TypeError("'coroutine' object is not iterable"), TypeError('vars() argument must have ...
Read more >
Common Mistakes Using Python3 asyncio
This "coroutine object" will be executed when current EventLoop gets a chance: awaited/yield from is called or all previous tasks are finished. To...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found