Python 用FastAPI简单注册Tortoise-ORM模型
我有一个FastAPI应用程序和一个现有的MySQL数据库,我正在尝试使用Ortoise ORM。 (简化的)主FastAPI文件如下所示:Python 用FastAPI简单注册Tortoise-ORM模型,python,fastapi,tortoise-orm,Python,Fastapi,Tortoise Orm,我有一个FastAPI应用程序和一个现有的MySQL数据库,我正在尝试使用Ortoise 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 DATA
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"))
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"
# Test SQL query
from models import Store
@app.on_event("startup")
async def startup():
print(await Store.get(api_key="api_key"))
…和一个models.py文件,位于相同的基本目录级别,如下所示:
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"))
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"
# Test SQL query
from models import Store
@app.on_event("startup")
async def startup():
print(await Store.get(api_key="api_key"))
但是,我从乌龟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
知道为什么吗
我遵循doc(),但是“应该为模型发现的模块”的路径/语法对我来说不是很清楚。我还尝试向pydantic\u model\u creator
注册模型,但文档中不清楚您为什么需要它()。
我不希望使用由register_tortoise加载的config.json完整配置文件,根据文档,它似乎是可选的。问题来自FastAPI和tortoise ORM的异步特性。 我们必须等待FastAPI加载,等待龟龟注册模型 因此,我们可以成功地执行一个异步请求,等待加载FastAPI,并请求Ortoise ORM,如下所示:
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"))
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"
# Test SQL query
from models import Store
@app.on_event("startup")
async def startup():
print(await Store.get(api_key="api_key"))
问题来自FastAPI和Ortoise ORM的异步特性。 我们必须等待FastAPI加载,等待龟龟注册模型 因此,我们可以成功地执行一个异步请求,等待加载FastAPI,并请求Ortoise ORM,如下所示:
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"))
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"
# 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寿命事件(即
启动
)的触发,并且没有注册模型。我们最后修补了中间件,使其仅在scope['type']
=='http'
时启动
声明即使在启动错误后服务器也必须继续
如果在使用lifespan.startup消息或lifespan类型的作用域调用可调用的应用程序时引发异常,则服务器必须继续,但不发送任何lifespan事件
然而,乌龟ORM注册\乌龟
功能依赖寿命事件启动
来注册模型。因此,我认为uvicorn的寿命模式应该是on
,而不是默认的auto
。这样,您的服务器进程将终止,而不是为配置错误的应用程序提供服务
uvicorn.run("start_server:app", host="0.0.0.0", port=8080, log_level="info", lifespan='on')
在我们的例子中,一个ASGI中间件(不支持ASGI寿命事件)在启动期间引发了一个错误,该错误阻止了ASGI寿命事件(即
启动
)的触发,并且没有注册模型。我们最后修补了中间件,使其仅在scope['type']
=='http'
时启动
声明即使在启动错误后服务器也必须继续
如果在使用lifespan.startup消息或lifespan类型的作用域调用可调用的应用程序时引发异常,则服务器必须继续,但不发送任何lifespan事件
然而,乌龟ORM注册\乌龟
功能依赖寿命事件启动
来注册模型。因此,我认为uvicorn的寿命模式应该是on
,而不是默认的auto
。这样,您的服务器进程将终止,而不是为配置错误的应用程序提供服务
uvicorn.run("start_server:app", host="0.0.0.0", port=8080, log_level="info", lifespan='on')
你在哪里运行应用程序?这可能是因为您在
app.py
文件上方的一个级别上启动它,因此需要在models.py
文件上方一个级别上启动它。如果您有app/main.py
和app/models.py
,那么路径是app.models
我没有使用任何app.py
文件,FastAPI应用程序在main.py
中实例化为app
,并且models.py
文件与main.py
处于同一级别。然后使用main.py
更改app.py
。运行该命令时,终端指向何处?在与main.py
相同的级别上或在上面的级别上?关于在终端中运行的命令,它与main.py
和models.py
在相同的级别上运行。关于main.py
,我不明白你的意思,因为一切都在同一个级别。1)这很奇怪。您的数据库中是否存在该架构?2) 因为我不知道你的主文件是如何调用的,所以我给它起了一个名字app.py
,但是因为你指出它main.py
,我只是简单地更改了它。你从哪里运行这个应用程序?这可能是因为您在app.py
文件上方的一个级别上启动它,因此需要在models.py
文件上方一个级别上启动它。如果您有app/main.py
和app/models.py
,那么路径是app.models
我没有使用任何app.py
文件,FastAPI应用程序在main.py
中实例化为app
,并且models.py
文件与main.py
处于同一级别。然后使用main.py
更改app.py
。运行该命令时,终端指向何处?在与main.py
相同的级别上或在上面的级别上?关于在终端中运行的命令,它与main.py
和models.py
在相同的级别上运行。关于main.py
,我不明白你的意思,因为一切都在同一个级别。1)这很奇怪。您的数据库中是否存在该架构?2) 因为我不知道主文件是如何调用的,所以我给它命名为app.py
,但是因为你指出它main.py
,我只是简单地更改了它。这是启动数据库连接的方法吗?通过提出请求?我们如何关闭?不,你必须先注册乌龟。这只是在发出请求之前等待启动。问题是,这是启动数据库连接的方法吗?通过提出请求?我们如何关闭?不,你必须先注册乌龟。这只是在发出请求之前等待启动。我有一个问题