Python FastAPI w/TortoiseORM:错误:无法处理的实体

Python FastAPI w/TortoiseORM:错误:无法处理的实体,python,python-3.x,fastapi,tortoise-orm,Python,Python 3.x,Fastapi,Tortoise Orm,我是fastAPI新手,正在尝试构建todo API。我用龟甲。我相信这个错误是由于在todo部分输入null值引起的,尽管我希望它为null或设置为默认值,这是一个空列表。这是与错误相关的代码。 main.py from typing import List import os from fastapi import FastAPI, Depends, HTTPException, status from models import User, Todo, User_pydantic, U

我是fastAPI新手,正在尝试构建todo API。我用龟甲。我相信这个错误是由于在todo部分输入null值引起的,尽管我希望它为null或设置为默认值,这是一个空列表。这是与错误相关的代码。 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())
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)
型号.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())
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)
当我试图创建一个新用户时,错误开始了。下面是来自swagger UI的错误

{
  "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"
    }
  ]
}

错误中说明了问题

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

我在您的
User
表中没有看到任何
todo\u id
列,但我想这只是因为复制和粘贴的问题

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

todo: fields.ForeignKeyNullableRelation[Todo, None] = fields.ForeignKeyField("models.Todo", related_name="todo")
这样,您就可以知道该字段的类型是
ForeignKeyNullableRelation
,或者
Todo
或者
None

这是我的猜测,太长了,不适合评论,所以我把它作为一个答案贴了出来


让我知道它是否有效。

我遇到了类似的问题,并找到了解决方案。这里的问题是,您的POST请求缺少
todo\u id
(不是
todo
,因为数据库会自动将
\u id
添加到相关字段中)。但如果您尝试添加它,您将得到
不允许的额外字段。
原因是
UserIn\u pydantic
没有此字段。要解决此问题,只需覆盖它:

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
并在您的main.py中替换您的类型注释。这样,您将被命名为POST
todo_id
,它将存储在数据库中,您将被命名为返回它


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

@Isabi很遗憾,你的代码不起作用。下面是我得到的错误
TypeError(f“太多{many'if alen>elen else'now}参数用于{cls};“TypeError:太多参数用于键入。Union[typing.waitable[typing.Union[~MODEL,NoneType]],~MODEL,NoneType];实际值2,预期值1
它只预期1个参数我不知道为什么todo列没有出现。更不用说FastAPI的OrtoiseRM文档只显示没有任何关系字段的简单模型,例如ForeignKeyField。那么todo:fields.ForeignKeyNullableRelation[todo]=fields.ForeignKeyField(“models.todo”)呢“,related_name=“todo”,null=True)?@Isabi我已经试过了。结果仍然是一样的,这太奇怪了。试着在github的回购协议上打开一个问题,让我知道