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

使用asyncpg驱动时,Tortoise ORM模型无法继承default_connection?

Tortoise-ORM PostgreSQL 配置下模型无法继承 default_connection 的问题

背景信息

我正在开发一个插件化系统,按需加载Tortoise-ORM(依赖配置为tortoise-orm = {extras = ["asyncpg"], version = "^0.19.3"})模型,测试模型代码如下:

class PingModel(Model):
    uid = fields.TextField()
    ping_count = fields.IntField()

    def __str__(self):
        return self.name

使用SQLite数据库时一切正常,但切换到PostgreSQL(asyncpg驱动)后,调用模型报错。数据库配置代码:

elif 'postgres' in self.config['database']:
    db_config = {
        'connections': {
            'default': {
                'engine': "tortoise.backends.asyncpg",
                'credentials': {
                    'host': self.config['database']['postgres']['db_url'],
                    'port': self.config['database']['postgres']['db_port'],
                    'user': self.config['database']['postgres']['db_user'],
                    'password': self.config['database']['postgres']['db_password'],
                    'database': self.config['database']['postgres']['db_name'],
                },
            },
        },
        'apps': {
            'models': {
                'models': self.models,
                'default_connection': 'default'
            },
        },
    }
[...]
await Tortoise.init(config=db_config)
await Tortoise.generate_schemas()

报错信息:

Traceback (most recent call last):
  File "/home/tunacado/.cache/pypoetry/virtualenvs/fishbot-5Nu9GTXz-py3.10/lib/python3.10/site-packages/discord/commands/core.py", line 124, in wrapped
    ret = await coro(arg)
  File "/home/tunacado/.cache/pypoetry/virtualenvs/fishbot-5Nu9GTXz-py3.10/lib/python3.10/site-packages/discord/commands/core.py", line 978, in _invoke
    await self.callback(self.cog, ctx, **kwargs)
  File "/home/tunacado/Source/fishbot/fishbot/cogs/ping.py", line 17, in ping
    record = await PingModel.filter(uid__contains=user)
  File "/home/tunacado/.cache/pypoetry/virtualenvs/fishbot-5Nu9GTXz-py3.10/lib/python3.10/site-packages/tortoise/models.py", line 1255, in filter
    return cls._meta.manager.get_queryset().filter(*args, **kwargs)
  File "/home/tunacado/.cache/pypoetry/virtualenvs/fishbot-5Nu9GTXz-py3.10/lib/python3.10/site-packages/tortoise/manager.py", line 15, in get_queryset
    return QuerySet(self._model)
  File "/home/tunacado/.cache/pypoetry/virtualenvs/fishbot-5Nu9GTXz-py3.10/lib/python3.10/site-packages/tortoise/queryset.py", line 299, in __init__
    super().__init__(model)
  File "/home/tunacado/.cache/pypoetry/virtualenvs/fishbot-5Nu9GTXz-py3.10/lib/python3.10/site-packages/tortoise/queryset.py", line 96, in __init__
    self.capabilities: Capabilities = model._meta.db.capabilities
  File "/home/tunacado/.cache/pypoetry/virtualenvs/fishbot-5Nu9GTXz-py3.10/lib/python3.10/site-packages/tortoise/models.py", line 285, in db
    raise ConfigurationError(
tortoise.exceptions.ConfigurationError: default_connection for the model <class 'fishbot.cogs.ping.PingModel'> cannot be None

确认传入的db_config内容正确:

{'connections': {'default': {'engine': 'tortoise.backends.asyncpg', 'credentials': {'host': 'localhost', 'port': 5432, 'user': 'myuser', 'password': 'mypassword', 'database': 'mydb'}}}, 'apps': {'models': {'models': ['fishbot.cogs.ping'], 'default_connection': 'default'}}}

尝试在模型中添加class Meta、手动修改Model._meta.default_connection均无效,直接指定模型类路径提示模块未找到。运行Tortoise官方PostgreSQL示例可正常工作,推测问题出在模型传递方式上。

问题

  1. 为什么模型无法继承配置中的default_connection?
  2. 使用Tortoise-ORM初始化PostgreSQL时,如何确保所有模型都设置好default_connection?

解答

问题1:模型无法继承default_connection的原因

核心原因是插件化按需加载模型的时机晚于Tortoise初始化流程。Tortoise在Tortoise.init()时会遍历配置中指定的模型模块,为每个模型绑定default_connection;但如果你的模型是在初始化之后才被动态加载的,这些后加载的模型就不会被Tortoise的初始化流程处理,自然无法继承配置中的连接信息。

另外,SQLite能正常工作是因为SQLite驱动对未绑定连接的模型有兼容逻辑,而asyncpg驱动的校验更严格,直接抛出了未配置连接的错误。

问题2:确保所有模型设置default_connection的方案

方案1:延迟Tortoise初始化,先收集所有模型再初始化

如果插件化系统支持先收集所有需要加载的模型模块路径,再调用Tortoise.init(),这是最稳妥的方式。比如在所有插件加载完毕后,将所有模型的模块路径汇总到self.models中,再执行初始化操作。

方案2:动态加载模型后手动注册到Tortoise

对于Tortoise初始化之后才加载的模型,可以手动调用内部方法完成注册:

from tortoise import Tortoise

# 假设PingModel是刚动态加载的模型
await Tortoise._init_model(PingModel, "models", "default")

其中"models"是你配置中apps里的应用名称,"default"是连接名称,要和db_config中的配置完全对应。

方案3:给模型添加Meta类指定连接

如果之前写法有误,正确的Meta类配置如下:

class PingModel(Model):
    uid = fields.TextField()
    ping_count = fields.IntField()

    def __str__(self):
        return self.name

    class Meta:
        default_connection = "default"

注意要确保"default"和配置中的连接名称一致,且该模型要在Tortoise初始化时被扫描到,或者后续手动注册。

方案4:修正动态加载逻辑,确保模型模块可被识别

如果直接指定模型类路径提示模块未找到,说明插件化加载逻辑未将模型所在模块添加到Python的sys.path,或者模块名称写法错误(比如应该是"fishbot.cogs.ping.PingModel"而非"fishbot.cogs.ping")。可以检查模块路径正确性,或在加载插件时将插件所在目录添加到sys.path。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:15:04