python-3.xflasktortoise-orm

What is the right way to initialize database using tortoise orm in flask app?


I learn flask, before I've complete chapter about tortoise ORM. I try to combine flask and tortoise and I can't find proper way. When I call async function I got error:

Traceback (most recent call last):
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 1867, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\_compat.py", line 39, in reraise
    raise value
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\_compat.py", line 39, in reraise
    raise value
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\flask\app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\Vladlen\python\pythonBasics\lesson 19\views\doc_income.py", line 19, in new
    run_async(create_doc(request.values['account_id'], request.values['sum']))
  File "C:\Users\Vladlen\python\pythonBasics\venv\lib\site-packages\tortoise\__init__.py", line 634, in run_async
    loop = asyncio.get_event_loop()
  File "C:\Users\Vladlen\AppData\Local\Programs\Python\Python37\lib\asyncio\events.py", line 644, in get_event_loop
    % threading.current_thread().name)
RuntimeError: There is no current event loop in thread 'Thread-7'.

piece of my code calling document creation:

@doc_income_app.route("new", methods=['GET', 'POST'])
def new():
    if request.method == 'GET':
        return render_template('doc_income/new.html')
    else:
        run_async(create_doc(request.values['account_id'], request.values['sum']))
        return jsonify(ok=True)


async def create_doc(account_id, sum):
    await db.init()
    doc = db.DocIncome(
        account_id=account_id,
        sum=sum
    )
    await doc.save()

My question is how to call async db manipulation code in flask application?


Solution

  • How to call async code from sync code?

    Create an event loop, and run code in there. Problem is the event loop has to clear out, so any scheduled tasks will make it never end. (A risk of doing run_until_complete) Basically:

    asyncio.get_event_loop().run_until_complete(create_doc(...))
    

    The run_async helper that tortoise provides also enforces that DB is cleaned up, so I'm uncertain it's what you want.

    Apologies, but you are essentially calling from an incompatible colour and is trailblazing, there isn't a texbook answer I can give.

    My original answer: Flask is a synchronous Python framework, it doesn't use an event loop. Consider using an asyncio-based framework, such as Quart/aiohttp/starlette, both that and Tortoise-ORM the uses the same concurrency method and it should work.