tortoise / tortoise/tortoise-orm
why will "Tortoise.init_models" raise a ConfigurationError
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 516
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 9
Description
Describe the bug
i'm a beginner for fastapi, i have a model that has a ForeignKeyRelation; i want to show this related field with "pydantic_model_creator" function; I learned that it is possible to set "Tortoise.init_models"; but i have a problem with it;
To Reproduce
Here is my application structure.
`
- ├── app
- │ ├── api
- │ │ ├── access_admin.py
- │ │ ├── Base.py
- │ │ ├── login.py
- │ │ ├── role_admin.py
- │ │ ├── test_auth.py
- │ │ ├── test_redis.py
- │ │ └── user.py
- │ ├── core
- │ │ ├── Auth.py
- │ │ ├── Events.py
- │ │ ├── Exception.py
- │ │ ├── Helper.py
- │ │ ├── Middleware.py
- │ │ ├── Response.py
- │ │ └── Router.py
- │ ├── curd
- │ │ └── user.py
- │ ├── database
- │ │ ├── mysql.py
- │ │ ├── redis.py
- │ │ └── sqlite.py
- │ ├── models
- │ │ ├── base.py
- │ │ └── serializers.py
- │ ├── schemas
- │ │ ├── access.py
- │ │ ├── base.py
- │ │ ├── role.py
- │ │ └── user.py
- │ └── views
- │ ├── Base.py
- │ ├── home.py
- │
- ├── config.py
- │
- ├── main.py
`
database connection is setup in app/database/mysql.py:
`
from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise
import os
from tortoise import Tortoise
DB_ORM_CONFIG = {
"connections" :{
"english_notes":{
'engine': 'tortoise.backends.mysql',
"credentials": {
'host': os.getenv('BASE_HOST', '127.0.0.1'),
'user': os.getenv('BASE_USER', 'notes'),
'password': os.getenv('BASE_PASSWORD', '961025.'),
'port': int(os.getenv('BASE_PORT', 3306)),
'database': os.getenv('BASE_DB', 'english_notes'),
}
}
},
"apps":{
"english_notes":{"models": ["app.models.base", "aerich.models"], "default_connection": "english_notes"},
"base" : {"models": ["app.models.base"], "default_connection": "english_notes"},
},
'use_tz': False,
'timezone': 'Asia/Shanghai'
}
async def register_mysql(app: FastAPI):
register_tortoise(
app,
config=DB_ORM_CONFIG,
generate_schemas=False,
add_exception_handlers=True,
)
model is in app/models/base.py:
from tortoise.models import Model
from tortoise import fields
class EnglishSentence(Model):
id = fields.IntField(pk=True)
original = fields.CharField(max_length=255, description="英语原文", unique=True)
translation = fields.CharField(max_length=255, description="中文翻译")
notes = fields.TextField(description="笔记", null=True)
create_time = fields.DatetimeField(auto_now_add=True, description='创建时间')
update_time = fields.DatetimeField(auto_now=True, description="更新时间")
auhtor: fields.ForeignKeyRelation["User"] = fields.ForeignKeyField("base.User", related_name="sentence", on_delete=fields.SET_NULL, null=True)
class Meta:
"""
对该数据库模型类进行相关 配置设置
"""
table_description = "英语笔记"
table = "notes"
# 建立索引
# 使用联合索引
indexes = (("original", "translation"),)
def __str__(self) -> str:
return self.original # type: ignore
class TimestampMixin(Model):
create_time = fields.DatetimeField(auto_now_add=True, description='创建时间')
update_time = fields.DatetimeField(auto_now=True, description="更新时间")
class Meta:
# 抽象类 - 继承 避免代码重写,抽象类本身不生成数据表
abstract = True
# table = None
# app = "base"
class User(TimestampMixin):
sentence : fields.ReverseRelation[EnglishSentence] # 仅用于代码提示,请注意role 必须和 EnglishSentence里面的外键 指定的related_name 同名
user_name = fields.CharField(null=True, max_length=20, description="用户名", unique=True)
user_type = fields.BooleanField(default=False, description="用户类型 True:超级管理员 False:普通管理员")
password = fields.CharField(null=True, max_length=255)
nickname = fields.CharField(default="Boziyoung", max_length=255, description='昵称')
user_phone = fields.CharField(null=True, max_length=11 ,description="手机号", unique=True)
user_email = fields.CharField(max_length=255, description="邮箱", unique=True)
full_name = fields.CharField(max_length=255, null=True, description="姓名")
user_status = fields.IntField(default=0, description='0未激活 1正常 2禁用')
header_img = fields.CharField(null=True, max_length=255, description='头像')
sex = fields.IntField(default=0, null=True, description='0未知 1男 2女')
client_host = fields.CharField(null=True, max_length=19, description="访问IP")
class Meta:
table_description = "用户表"
table = "user"
app = "base"
`
The relationship of the above model is "ForeignKeyField" in EnglishSentence model;
The serialization model is app/model/serializers.py:
`"""
创建各个序列化对象
"""
from app.models.base import EnglishSentence, User
from tortoise.contrib.pydantic.creator import pydantic_model_creator, pydantic_queryset_creator
from tortoise import Tortoise
Tortoise.init_models(["app.models.base"], "models")
admin_english = pydantic_model_creator(EnglishSentence, name= "admin")
list_english = pydantic_queryset_creator(EnglishSentence, name= "list_english", exclude=("notes","create_time", "update_time", "original"))
single_english = pydantic_model_creator(EnglishSentence, name="single_english", exclude=("update_time", "create_time"))
single_english_queryset = pydantic_queryset_creator(EnglishSentence, name="single_english_list", exclude=("notes","create_time", "update_time", "original"))
single_user = pydantic_model_creator(User, name="single_user", exclude=("password", "remarks", "client_host", "create_time", "update_time",))`
i new added a line of code which is "Tortoise.init_models(["app.models.base"], "models")"
but it raised a ConfigurationError
Detailed error :
`WARNING: WatchFiles detected changes in 'app/models/serializers.py'. Reloading...
Process SpawnProcess-35:
Traceback (most recent call last):
File "/home/ubuntu/english/env/lib/python3.11/site-packages/tortoise/init.py", line 119, in get_related_model
return cls.apps[related_app_name][related_model_name]
~~~~~~~~^^^^^^^^^^^^^^^^^^
KeyError: 'base'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.11/multiprocessing/process.py", line 314, in _bootstrap
self.run()
File "/usr/lib/python3.11/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/home/ubuntu/english/env/lib/python3.11/site-packages/uvicorn/_subprocess.py", line 76, in subprocess_started
target(sockets=sockets)
File "/home/ubuntu/english/env/lib/python3.11/site-packages/uvicorn/server.py", line 59, in run
return asyncio.run(self.serve(sockets=sockets))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "uvloop/loop.pyx", line 1517, in uvloop.loop.Loop.run_until_complete
File "/home/ubuntu/english/env/lib/python3.11/site-packages/uvicorn/server.py", line 66, in serve
config.load()
File "/home/ubuntu/english/env/lib/python3.11/site-packages/uvicorn/config.py", line 471, in load
self.loaded_app = import_from_string(self.app)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/english/env/lib/python3.11/site-packages/uvicorn/importer.py", line 21, in import_from_string
module = importlib.import_module(module_str)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/importlib/init.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "", line 1206, in _gcd_import
File "", line 1178, in _find_and_load
File "", line 1149, in _find_and_load_unlocked
File "", line 690, in _load_unlocked
File "", line 940, in exec_module
File "", line 241, in _call_with_frames_removed
File "/home/ubuntu/english/english_backend/main.py", line 11, in
from app.core.Router import AllRouter
File "/home/ubuntu/english/english_backend/app/core/Router.py", line 4, in
from app.api.Base import ApiRouter
File "/home/ubuntu/english/english_backend/app/api/Base.py", line 48, in
from app.api.user import user_add, user_del, user_info, get_user_rules, account_login, user_edit, change_password
File "/home/ubuntu/english/english_backend/app/api/user.py", line 14, in
from app.models.serializers import single_user
File "/home/ubuntu/english/english_backend/app/models/serializers.py", line 9, in
Tortoise.init_models(["app.models.base"], "models")
File "/home/ubuntu/english/env/lib/python3.11/site-packages/tortoise/init.py", line 396, in init_models
cls._init_relations()
File "/home/ubuntu/english/env/lib/python3.11/site-packages/tortoise/init.py", line 161, in _init_relations
related_model = get_related_model(related_app_name, related_model_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/ubuntu/english/env/lib/python3.11/site-packages/tortoise/init.py", line 122, in get_related_model
raise ConfigurationError(f"No app with name '{related_app_name}' registered.")
tortoise.exceptions.ConfigurationError: No app with name 'base' registered.
`
Expected results:
I don't know what I should do, I hope you all can help me to solve it; thank you.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with app/models/serializers.py and the Tortoise.init_models call, then compare it with the configuration in app/database/mysql.py and the models in app/models/base.py. Reproduce the reported ConfigurationError and trace how the registered app names relate to the ForeignKeyField declaration. Done means documenting or testing the supported initialization path and its expected result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fastapi, mysql, python
- Domain
- api, backend, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100