带TortoiseORM的FastAPI:错误:无法处理的实体

问题描述

我是fastAPI的新手,正在尝试构建todo API。我使用Tortoise-ORM。我相信该错误是由于在todo部分输入空值引起的,尽管我希望它为空或设置为认值(这是一个空列表)。这是与错误相关的代码 main.py

from typing import List
import os

from fastapi import FastAPI,Depends,HTTPException,status

from models import User,Todo,User_pydantic,UserIn_pydantic,Todo_pydantic,TodoIn_pydantic
from tortoise.contrib.fastapi import register_tortoise,HTTPNotFoundError

app = FastAPI()

@app.post("/users/",response_model=User_pydantic)
async def create_user(user: UserIn_pydantic):
    user_obj = await User.create(**user.dict(exclude_unset=True))
    return await User_pydantic.from_tortoise_orm(user_obj)


@app.get("/users/",response_model=List[User_pydantic])
async def read_all_users():
    return await User_pydantic.from_queryset(User.all())

models.py

from tortoise.models import Model
from tortoise import fields
from tortoise.contrib.pydantic import pydantic_model_creator


class Todo(Model):
    id = fields.IntField(pk=True)
    title = fields.CharField(500)
    description = fields.TextField(null=True)

Todo_pydantic = pydantic_model_creator(Todo,name="Todo")
TodoIn_pydantic = pydantic_model_creator(Todo,name="TodoIn",exclude_readonly=True)

class User(Model):
    id = fields.IntField(pk=True)
    username = fields.CharField(500,unique=True)
    email = fields.CharField(100,unique=True)
    password = fields.CharField(100)
    is_active = fields.BooleanField(default=True)
    todo: fields.ForeignKeyNullableRelation[Todo] = fields.ForeignKeyField("models.Todo",related_name="todo")

    class PydanticMeta:
        exclude = ["is_active","todo"]

User_pydantic = pydantic_model_creator(User,name="User")
UserIn_pydantic = pydantic_model_creator(User,name="UserIn",exclude_readonly=True)

当我尝试创建新用户时,错误开始。这是大张旗鼓的用户界面错误

{
  "detail": [
    {
      "loc": [],"msg": "null value in column \"todo_id\" of relation \"user\" violates not-null constraint\nDETAIL:  Failing row contains (6,bob,bob@email.com,bob123,t,null).","type": "IntegrityError"
    }
  ]
}

解决方法

问题在错误中指出

“关系“用户”的列“ todo_id”中的空值违反 非空约束\ n详细信息:失败行包含(6,bob, bob@email.com,bob123,t,null)。

在您的todo_id表中没有看到任何User列,但是我想这只是由于在SO上复制和粘贴存在问题。

我还没有使用过TortoiseORM(但是我想在它达到稳定版本后使用它),但是您是否尝试过将todo的定义更改为以下内容?

todo: fields.ForeignKeyNullableRelation[Todo,None] = fields.ForeignKeyField("models.Todo",related_name="todo")

通过这种方式,您可以知道该字段的类型为ForeignKeyNullableRelation,并且为TodoNone

这是我的猜测,太长了,无法放入评论中,因此我将其发布为答案。

让我知道它是否有效。

,

我遇到了类似的问题并找到了解决方案。这里的问题是您的 POST 请求缺少 todo_id(不是 todo,因为数据库会自动将 _id 添加到相关字段)。但是如果您尝试添加它,您将获得 extra fields not permitted。 原因是因为 UserIn_pydantic 没有这个字段。要解决它,首先尝试通过调用 init_models 来初始化您的模型:

Tortoise.init_models(['path_to_file_with_models'],'models')

pydantic_model_creator 之后应该做剩下的事情,它适用于大多数情况。如果没有,那么只需简单地覆盖它:

UserIn_pydantic = pydantic_model_creator(User,name="UserIn",exclude_readonly=True)

class UsersIn_PydanticWithRelation(UsersIn_Pydantic):
    todo_id: int

User_pydantic = pydantic_model_creator(User,name="User")
class Users_PydanticWithRelation(Users_Pydantic):
   client_id: int

并在您的 ma​​in.py 中替换您的类型注释。这样您就可以 POST todo_id,它将存储在数据库中,您可以返回它。

至少这对我有用。我希望它也能帮助你。如果有帮助,请告诉我。