首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Fastapi/Tortoise早期模型初始化

Fastapi/Tortoise早期模型初始化
EN

Stack Overflow用户
提问于 2021-04-26 03:13:44
回答 1查看 619关注 0票数 3

我有以下关于fastapi的实现。

我目前的问题是,我无论如何也不能在乌龟模型上执行early init来将关系恢复到模式中。

我已经尝试过将下面这行代码转储到所有地方,但似乎就是不起作用。

代码语言:javascript
运行
复制
Tortoise.init_models(["models.user", "models.group"], "models")

我也尝试过以这种方式使用prefetch_related,但也不起作用

代码语言:javascript
运行
复制
GetGroup.from_queryset(Group.get(id=3).prefetch_related('owner'))

我已经用谷歌搜索了几个小时,还没有找到一个具体的答案/方法来让它正常工作。

文件夹结构:

代码语言:javascript
运行
复制
app
│   main.py
└───database
│   │   database.py
└───models
|    │   user.py
|    │   group.py
└───routers
|   │   user_router.py
|   │   group_router.py
└───services
|   │   auth.py

main.py

代码语言:javascript
运行
复制
from fastapi import FastAPI
from database.database import init_db
from routers.user_router import router as UserRouter
from routers.group_router import router as GroupRouter

# Instantiate the Application
app = FastAPI(title="test", root_path="/api/")

# Include the Routers
app.include_router(UserRouter, tags=["User"], prefix="/user")
app.include_router(GroupRouter, tags=["Group"], prefix="/group")


# Start DB Connection on Startup
@app.on_event("startup")
async def startup_event():
    init_db(app)

database/database.py

代码语言:javascript
运行
复制
from decouple import config
from fastapi import FastAPI
from tortoise import Tortoise
from tortoise.contrib.fastapi import register_tortoise


def init_db(app: FastAPI) -> None:
    Tortoise.init_models(["models.user", "models.group"], "models")
    register_tortoise(
        app,
        db_url=f"mysql://{config('MYSQL_USER')}:{config('MYSQL_PASSWORD')}@{config('MYSQL_HOST')}:{config('MYSQL_EXPOSE')}/{config('MYSQL_DB')}",
        modules={"models": ["models.user",
                            "models.group",
                            ]},
        generate_schemas=False,
        add_exception_handlers=True,
    )


TORTOISE_ORM = {
    "connections": {"default": f"mysql://{config('MYSQL_USER')}:{config('MYSQL_PASSWORD')}@{config('MYSQL_HOST')}:{config('MYSQL_EXPOSE')}/{config('MYSQL_DB')}"},
    "apps": {
        "models": {
            "models": ["models.user",
                       "models.group",
                       "aerich.models"],
            "default_connection": "default",
        },
    },
}

models/user.py

代码语言:javascript
运行
复制
from tortoise import fields
from tortoise.models import Model
from tortoise.contrib.pydantic import pydantic_model_creator
from models.group import Group


class User(Model):
    # ##### Define Readonly Fields ##### #
    id = fields.BigIntField(pk=True)
    # ##### Define Normal Fields ##### #
    first_name = fields.CharField(max_length=50)
    last_name = fields.CharField(max_length=50)
    username = fields.CharField(max_length=50, unique=True)
    email = fields.CharField(max_length=50, unique=True)
    password = fields.CharField(max_length=128)
    # ##### Define O2M ##### #
    owned_groups: fields.ReverseRelation[Group]
    # ##### Define M2M ##### #
    groups: fields.ManyToManyRelation[Group]
    # ##### Define Time_Stamps ###### #
    created_at = fields.DatetimeField(auto_now_add=True)
    modified_at = fields.DatetimeField(auto_now=True)

    class Meta:
        table: str = 'users'


AuthData = pydantic_model_creator(User)
CreateUser = pydantic_model_creator(User, name="CreateUser", exclude_readonly=True)
UpdateUser = pydantic_model_creator(User, name="UpdateUser", exclude_readonly=True, exclude=['password'])
GetUser = pydantic_model_creator(User, name="GetUser", exclude=['password'])
ChangeUserPassword = pydantic_model_creator(User, name="ChangeUserPassword", exclude_readonly=True, include=['password'])

models/group.py

代码语言:javascript
运行
复制
from tortoise import fields
from tortoise.models import Model
from tortoise.contrib.pydantic import pydantic_model_creator


class Group(Model):
    # ##### Define Readonly Fields ##### #
    id = fields.BigIntField(pk=True)
    # ##### Define Normal Fields ##### #
    name = fields.CharField(max_length=50, unique=True)
    # ##### Define O2M ##### #
    owner = fields.ForeignKeyField("models.User", related_name="owned_groups")
    # ##### Define M2M ##### #
    members = fields.ManyToManyField("models.User", related_name="groups")
    # ##### Define Time_Stamps ###### #
    created_at = fields.DatetimeField(auto_now_add=True)
    modified_at = fields.DatetimeField(auto_now=True)

    class Meta:
        table: str = 'groups'


CreateGroup = pydantic_model_creator(Group, name="CreateGroup", exclude_readonly=True, exclude=['members'])
UpdateGroup = pydantic_model_creator(Group, name="UpdateGroup", exclude_readonly=True, exclude=['members'])
GetGroup = pydantic_model_creator(Group, name="GetGroup")

routers/group_router.py

代码语言:javascript
运行
复制
from typing import List
import json
from fastapi import HTTPException, APIRouter, Depends, status
from models.user import User
from models.group import Group, CreateGroup, UpdateGroup, GetGroup
from tortoise.contrib.fastapi import HTTPNotFoundError
from services.auth import current_user

# Intialize Router
router = APIRouter()


# ###################### Define Routes ###################### #

# Create A Group
@router.post("/", dependencies=[Depends(current_user)])
async def create_group(group: CreateGroup, user: User = Depends(current_user)):
    user = await user
    try:
        await Group.create(**group.dict(exclude_unset=True), owner_id=user.id)
    except Exception:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail="Group Name Already Exists"
        )
    return {"Group Created Successfully"}


# Update A Group
@router.put("/{group_id}", dependencies=[Depends(current_user)], responses={404: {"model": HTTPNotFoundError}})
async def update_group(group_id: int, group: UpdateGroup, user: User = Depends(current_user)):
    user = await user
    group = await GetGroup.from_queryset_single(Group.get(id=group_id))
    return group
    if user.id == group.id:
        await Group.filter(id=group_id).update(**group.dict(exclude_unset=True))
        return {"Group Successfully Updated"}
    else:
        raise HTTPException(
            status_code=status.HTTP_406_NOT_ACCEPTABLE,
            detail="You can't edit a group unless you're the owner"
        )


# Get All Groups
@router.get("/", dependencies=[Depends(current_user)])
async def get_groups():
    return GetGroup.schema()

正如您所看到的,最后一行GetGroup.schema()永远不会返回关系。

我尝试在容器启动时捕获日志,得到以下结果

代码语言:javascript
运行
复制
[2021-04-24 19:59:53 +0000] [1255] [INFO] Started server process [1255]
[2021-04-24 19:59:53 +0000] [1255] [INFO] Waiting for application startup.
[2021-04-24 19:59:53 +0000] [1255] [ERROR] Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/tortoise/__init__.py", line 358, in _discover_models
module = importlib.import_module(models_path)
File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
File "<frozen importlib._bootstrap>", line 991, in _find_and_load
File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 526, in lifespan
async for item in self.lifespan_context(app):
File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 467, in default_lifespan
await self.startup()
File "/usr/local/lib/python3.8/site-packages/starlette/routing.py", line 502, in startup
await handler()
File "/app/main.py", line 17, in startup_event
init_db(app)
File "/app/database/database.py", line 8, in init_db
Tortoise.init_models("app.models.user", "models")
File "/usr/local/lib/python3.8/site-packages/tortoise/__init__.py", line 415, in init_models
app_models += cls._discover_models(models_path, app_label)
File "/usr/local/lib/python3.8/site-packages/tortoise/__init__.py", line 360, in _discover_models
raise ConfigurationError(f'Module "{models_path}" not found')
tortoise.exceptions.ConfigurationError: Module "a" not found
[2021-04-24 19:59:53 +0000] [1255] [ERROR] Application startup failed. Exiting.

注意,它会执行几秒钟,然后应用程序就会正确启动,我还尝试将pydantic模型的创建分离到一个名为'schema‘的单独文件夹中,但也没有做任何事情

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-26 06:13:13

所以我终于找到了答案,我把它留在这里,以防某个可怜的人偶然发现这个问题

诀窍就是移动

代码语言:javascript
运行
复制
from database.database import init_db

添加到main.py文件的顶部

并添加

代码语言:javascript
运行
复制
Tortoise.init_models(["models.user", "models.group"], "models")

在init_db()函数下面,以便在执行register_tortoise函数和初始化所有模型之前调用它

信息来源:https://stackoverflow.com/a/65881146/13637905

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67257307

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档