微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用FastAPI轻松注册Tortoise ORM模型

如何解决使用FastAPI轻松注册Tortoise ORM模型

我有一个带有现有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

知道为什么吗?

我想这可能是我将模型模块注册到Tortoise的方式。 我正在关注文档(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)。 我宁愿不要使用register_tortoise加载的config.json完整配置文件,根据文档看来这是可选的。

解决方法

问题来自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"))
,

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

ASGI spec 声明即使在启动错误后服务器也必须继续运行。

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

然而,tortoise ORM register_tortoise 函数依赖于生命周期事件 startup 来注册模型。所以我认为 uvicorn 的寿命模式应该是 on 而不是默认的 auto。这样,您的服务器进程将终止,而不是为配置错误的应用提供服务。

uvicorn.run("start_server:app",host="0.0.0.0",port=8080,log_level="info",lifespan='on')

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。