dia*_*sis 5 python python-3.x fastapi
我正在尝试上传图像,但 FastAPI 返回时出现一个我无法弄清楚的错误。
file: UploadFile = File(...)如果我从函数定义中省略“ ”,它就会正常工作。但是当我将 the 添加file到函数定义中时,它会抛出错误。
这是完整的代码。
@router.post('/', response_model=schemas.PostItem, status_code=status.HTTP_201_CREATED)
def create(request: schemas.Item, file: UploadFile = File(...), db: Session = Depends(get_db)):
new_item = models.Item(
name=request.name,
price=request.price,
user_id=1,
)
print(file.filename)
db.add(new_item)
db.commit()
db.refresh(new_item)
return new_item
Run Code Online (Sandbox Code Playgroud)
Pydantic模型Item只是
class Item(BaseModel):
name: str
price: float
Run Code Online (Sandbox Code Playgroud)
错误是:
代码 422 错误:无法处理的实体
{
"detail": [
{
"loc": [
"body",
"request",
"name"
],
"msg": "field required",
"type": "value_error.missing"
},
{
"loc": [
"body",
"request",
"price"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
Run Code Online (Sandbox Code Playgroud)
问题是您的路由需要两种类型的请求正文:
request: schemas.Item
application/json正文file: UploadFile = File(...)
multipart/form-datamultipart/form-data”这是行不通的,因为这不仅破坏了 FastAPI,还破坏了通用的 HTTP 协议。FastAPI 在使用时的警告File中提到了这一点:
您可以在路径操作中声明多个
Fileand参数,但也不能声明您希望接收为 JSON 的字段,因为请求将使用而不是使用.FormBodymultipart/form-dataapplication/json这不是FastAPI的限制,它是 HTTP 协议的一部分。
正如将文件和关联数据发布到 RESTful WebService(最好以 JSON 形式)中所述,常见的解决方案是:
multipart/form-data幸运的是,FastAPI 支持解决方案 2,将您的模型组合起来Item并将文件上传到 1 中multipart/form-data。请参阅请求表格和文件部分:
当您需要在同一请求中接收数据和文件时,请一起使用
File和。Form
这是您修改后的路线(我删除了,db因为这与问题无关):
class Item(BaseModel):
name: str
price: float
class PostItem(BaseModel):
name: str
@router.post('/', response_model=PostItem, status_code=status.HTTP_201_CREATED)
def create(
# Here we expect parameters for each field of the model
name: str = Form(...),
price: float = Form(...),
# Here we expect an uploaded file
file: UploadFile = File(...),
):
new_item = Item(name=name, price=price)
print(new_item)
print(file.filename)
return new_item
Run Code Online (Sandbox Code Playgroud)
Swagger 文档将其呈现为 1 种形式
...您现在应该能够Item在一个请求中发送参数和文件。
如果您不喜欢将Item模型拆分为单独的参数(对于具有许多字段的模型来说确实很烦人),请参阅此 Q&A on fastapi form data with pydantic model。
下面是修改后的代码,其中Item更改为ItemForm支持接受其字段作为Form值而不是 JSON:
class ItemForm(BaseModel):
name: str
price: float
@classmethod
def as_form(cls, name: str = Form(...), price: float = Form(...)) -> 'ItemForm':
return cls(name=name, price=price)
class PostItem(BaseModel):
name: str
@router.post('/', response_model=PostItem, status_code=status.HTTP_201_CREATED)
def create(
item: ItemForm = Depends(ItemForm.as_form),
file: UploadFile = File(...),
):
new_item = Item(name=item.name, price=item.price)
print(new_item)
print(file.filename)
return new_item
Run Code Online (Sandbox Code Playgroud)
Swagger UI 应该仍然相同(所有字段Item和文件上传都在一种表单中)。
为了这:
file: UploadFile = File(...)如果我从函数定义中省略“ ”,它就会正常工作
关注这一点并不重要,但它确实有效,因为删除File会将预期的请求正文恢复为application/json类型,因此 JSON 正文将起作用。
最后,作为旁注,我强烈建议不要用作request路线的参数名称。除了含糊不清(一切都是请求)之外,直接使用Request对象request: Request时可能会与FastAPI的参数发生冲突。
| 归档时间: |
|
| 查看次数: |
5126 次 |
| 最近记录: |