1

我有一个带有现有 MySQL 数据库的 FastAPI 应用程序,我正在尝试使用 Tortoise ORM。(简化的)FastAPI 主文件如下所示:

from fastapi import FastAPI
import os
from tortoise.contrib.fastapi import register_tortoise

# Register FastAPI main app
app = FastAPI(title="my_app")


# Database
DATABASE_URL = "mysql://{}:{}@{}:{}/{}".format(
    os.environ["MYSQL_USER"],
    os.environ["MYSQL_PASSWORD"],
    os.environ.get("MYSQL_HOST", "127.0.0.1"),
    os.environ.get("MYSQL_PORT", "3306"),
    os.environ.get("MYSQL_DB", "my_db"),
)

# Register Tortoise ORM with DB
register_tortoise(
    app,
    db_url=DATABASE_URL,
    modules={"models": ["models"]},
    generate_schemas=False,
    add_exception_handlers=True,
)


# Test SQL query
from models import Store
print(Store.get(api_key="api_key"))

...和一个 models.py 文件,在同一基本目录级别,如下所示:

from tortoise import fields
from tortoise.models import Model


class Store(Model):
    api_key = fields.CharField(max_length=64, db_index=True)
    name = fields.CharField(max_length=255)

    def __str__(self):
        return self.name

    class Meta:
        table = "stores"

但是,我从 Tortoise ORM 得到一个错误:

  File ".../site-packages/tortoise/models.py", line 265, in db
    raise ConfigurationError("No DB associated to model")
tortoise.exceptions.ConfigurationError: No DB associated to model

知道为什么吗?

我正在关注文档(https://tortoise-orm.readthedocs.io/en/latest/contrib/fastapi.html),但是“应该为模型发现的模块”的路径/语法对我来说不是很清楚. 我还尝试使用 注册模型pydantic_model_creator,但在文档中不清楚为什么需要它(https://tortoise-orm.readthedocs.io/en/latest/examples/fastapi.html#example-fastapi)。我宁愿不使用 config.json 加载的完整配置文件register_tortoise,根据文档,它似乎是可选的。

4

2 回答 2

0

问题来自 FastAPI 和 Tortoise ORM 的异步特性。我们必须等待 FastAPI 加载并等待 Tortoise 注册模型。

所以我们可以成功地执行一个异步请求,等待 FastAPI 加载,然后 Tortoise ORM 请求,如下所示:

# Test SQL query
from models import Store

@app.on_event("startup")
async def startup():
    print(await Store.get(api_key="api_key"))
于 2020-11-27T08:39:54.100 回答
0

在我们的案例中,其中一个 ASGI 中间件(不支持 asgi 生命周期事件)在启动期间引发错误,导致 ASGI 生命周期事件(即startup)无法触发并且没有注册模型。我们最终修补了中间件,只为scope['type']==触发'http'

ASGI 规范指出,即使在启动错误之后,服务器也必须继续运行。

如果在使用 lifespan.startup 消息或具有生命周期类型的范围调用可调用应用程序时引发异常,则服务器必须继续但不发送任何生命周期事件。

然而,乌龟 ORMregister_tortoise函数依赖于生命周期事件startup来注册模型。所以我认为 uvicorn 上的 lifespan mode 应该on不是 default auto。这样,您的服务器进程将终止,而不是为配置错误的应用程序提供服务。

uvicorn.run("start_server:app", host="0.0.0.0", port=8080, log_level="info", lifespan='on')
于 2021-04-30T10:48:25.267 回答