Python FastAPI w/TortoiseORM:错误:无法处理的实体
我是fastAPI新手,正在尝试构建todo API。我用龟甲。我相信这个错误是由于在todo部分输入null值引起的,尽管我希望它为null或设置为默认值,这是一个空列表。这是与错误相关的代码。 main.pyPython 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
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中替换您的类型注释。这样,您将被命名为POSTtodo_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的回购协议上打开一个问题,让我知道