You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Flask应用中使用Tortoise ORM初始化数据库及调用异步代码的方法

Flask + Tortoise ORM:正确初始化与异步调用方案

看起来你在整合Flask和Tortoise ORM时踩了两个典型的坑:数据库初始化时机错误,以及在Flask的同步请求线程中调用异步函数时的事件循环问题。我来一步步帮你解决:

一、数据库初始化的正确姿势

绝对不要在每个请求的异步函数里调用await db.init()——这会重复创建数据库连接,既浪费资源又影响性能。正确的做法是在Flask应用启动时一次性完成初始化:

首先定义你的Tortoise配置和初始化函数:

from flask import Flask
from tortoise import Tortoise

app = Flask(__name__)

# 替换成你的数据库配置
TORTOISE_ORM = {
    "connections": {
        "default": "sqlite:///your_database.db"  # 可替换为PostgreSQL、MySQL等数据库链接
    },
    "apps": {
        "your_app_name": {
            "models": ["your_app.models"],  # 指向你的模型文件所在路径
            "default_connection": "default",
        }
    }
}

async def init_db():
    # 初始化Tortoise连接
    await Tortoise.init(config=TORTOISE_ORM)
    # 自动生成表结构(生产环境建议改用迁移工具,关闭此选项)
    await Tortoise.generate_schemas()

然后在应用启动时执行初始化:

if __name__ == "__main__":
    # 用Tortoise的run_async在主线程运行初始化逻辑
    from tortoise import run_async
    run_async(init_db())
    app.run(debug=True)

如果是用WSGI服务器(比如Gunicorn)部署,没法直接在__main__里执行,可以用标记变量配合before_request确保只初始化一次:

db_initialized = False

@app.before_request
def setup_db():
    global db_initialized
    if not db_initialized:
        from tortoise import run_async
        run_async(init_db())
        db_initialized = True

二、在Flask请求中调用异步数据库操作

你遇到的RuntimeError: There is no current event loop in thread 'Thread-7'错误,是因为Flask默认会为每个请求分配独立的子线程,而asyncio不会在子线程中自动创建事件循环。这里有两种靠谱的解决方式:

方式1:手动创建并管理事件循环

直接在请求处理函数里创建事件循环,运行异步任务后关闭:

import asyncio
from flask import request, jsonify, render_template

@doc_income_app.route("new", methods=['GET', 'POST'])
def new():
    if request.method == 'GET':
        return render_template('doc_income/new.html')
    else:
        # 创建新的事件循环并设置为当前线程的默认循环
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        # 运行异步任务直到完成
        loop.run_until_complete(create_doc(request.values['account_id'], request.values['sum']))
        loop.close()
        return jsonify(ok=True)

async def create_doc(account_id, sum):
    # 无需再初始化db,启动时已完成全局初始化
    doc = db.DocIncome(
        account_id=account_id,
        sum=sum
    )
    await doc.save()

方式2:用asgiref.sync简化异步转同步

这是更简洁的方案,asgiref的async_to_sync工具会自动帮你处理事件循环的创建和管理:

先安装依赖:

pip install asgiref

然后修改请求处理函数:

from asgiref.sync import async_to_sync
from flask import request, jsonify, render_template

@doc_income_app.route("new", methods=['GET', 'POST'])
def new():
    if request.method == 'GET':
        return render_template('doc_income/new.html')
    else:
        # 直接将异步函数转为同步调用
        async_to_sync(create_doc)(request.values['account_id'], request.values['sum'])
        return jsonify(ok=True)

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

额外提醒

  • 尽量避免在异步函数里做阻塞操作(比如同步IO),否则会抵消异步的性能优势。
  • 如果你的应用有大量异步操作需求,更推荐使用支持ASGI的框架(比如FastAPI)配合Tortoise ORM,这样异步代码的编写会更自然流畅。

内容的提问来源于stack exchange,提问作者vladlen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 16:37:34