12

The following doesn't execute foo and gives RuntimeWarning: coroutine 'foo' was never awaited

# urls.py

async def foo(data):
    # process data ...

@api_view(['POST'])
def endpoint(request):
    data = request.data.get('data')
    
    # How to call foo here?
    foo(data)

    return Response({})
3
  • 1
    await foo(data) ? Commented Jun 15, 2020 at 14:27
  • await foo(data) gives SyntaxError: invalid syntax Commented Jun 15, 2020 at 14:29
  • 1
    Your view function must be defined with async keyword Commented Jun 15, 2020 at 14:35

4 Answers 4

15

Django is an synchronous language but it supports Async behavior. Sharing the code snippet which may help.

    import asyncio
    from channels.db import database_sync_to_async

    def get_details(tag):
        response = another_sync_function()

        # Creating another thread to execute function
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        async_result = loop.run_until_complete(remove_tags(response, tag))
        loop.close()

    # Async function 
    async def remove_tags(response, tag_id):
        // do something here

        # calling another function only for executing database queries
        await tag_query(response, tag_id)

   @database_sync_to_async
   def tag_query(response, tag_id):
        Mymodel.objects.get(all_tag_id=tag_id).delete()

This way i called async function in synchronous function.

Reference for database sync to async decorator

Sign up to request clarification or add additional context in comments.

1 Comment

How to do this on class based view?
8

Found a way to do it.

Create another file bar.py in the same directory as urls.py.

# bar.py

def foo(data):
    // process data
# urls.py

from multiprocessing import Process
from .bar import foo

@api_view(['POST'])
def endpoint(request):
    data = request.data.get('data')

    p = Process(target=foo, args=(data,))
    p.start()

    return Response({})

2 Comments

Tried this with data being a form and foo being a function to process that form (or more correct; changing some values depending of the value in the form). That didnt work...
yes, this worked! it's non blocking.
0

You can't await foo in this context. Seeing that Django is mainly a synchronous library, it doesn't interact well with asynchronous code. The best advice I can give it to try avoid using an asynchronous function here, or perhaps use another method of concurrency (ie threading or multiprocessing).

Note: there is a great answer given about Django's synchronous nature that can be found here: Django is synchronous or asynchronous?.

2 Comments

Django 3.X support async
How do you have other methods of concurrency without asynchronicity? What benefit would you be hoping to gain?
0

for me using Django 2.2.12 and python 3.6.15, I used asyncio lib:

import asyncio

def async_trigger(my_async_task, *args, **kwargs):
    try:
        loop = asyncio.get_event_loop()
    except RuntimeError:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)

    if loop.is_running():
        loop.create_task(my_async_task(*args, **kwargs))
    else:
        loop.run_until_complete(my_async_task(*args, **kwargs))


async def foo(data):
    # process data ...

@api_view(['POST'])
def endpoint(request):
    data = request.data.get('data')
  
    async_trigger(foo, data)

    return Response({})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.