Search code examples
pythonpython-3.xdjangoasync-awaitdjango-channels

django async if else use a thread or sync_to_async


I don't know where the error is.

I am using Django ORM asynchronously.

@database_sync_to_async
def filter_data(**kwargs):
    return FinishAnimateModel.objects.filter(**kwargs)
async def receive(self, text_data=None, bytes_data=None):
    ...
    if data['msg']:
        print('in')
        model = await DB.Myself.filter_data(name__contains='')
        print('ok')
    else:
        print('else')
        model = await DB.Myself.filter_data(name__contains='')
        print(model, 'model')

In if log

in
ok

In else log

else
You cannot call this from an async context - use a thread or sync_to_async.

I try to reverse if else.

async def receive(self, text_data=None, bytes_data=None):
    ...
    if not data['msg']:
        pass
    else:
        print('else')
        model = await DB.Myself.filter_data(name__contains='')
        print(model, 'model')

In else log

else
You cannot call this from an async context - use a thread or sync_to_async.

Why?

Can you help me?


Solution

  • It looks like it could be passed in the if part only because you didn't print(model) in there. If you do, then you should see the same problem.

    However, I may not be able to answer the question you asked -- It's too little information.

    All I can say is that the type returned by filter() is QuerySet, if you want to print it, you must convert it to list type.

    Reference: Retrieving specific objects with filters

    So, maybe you can modify it like this:

    async def receive(self, text_data=None, bytes_data=None):
        ...
        if not data['msg']:
            print('in')
            model = list(await DB.Myself.filter_data(name__contains=''))
            print(model, 'ok')
        else:
            print('else')
            model = list(await DB.Myself.filter_data(name__contains=''))
            print(model, 'model')
    

    Or

    @database_sync_to_async
    def filter_data(**kwargs):
        return list(FinishAnimateModel.objects.filter(**kwargs))