此问题已在此处有答案:
How to post JSON data to FastAPI backend without using Swagger UI?(1个答案)
2天前关闭。
我正在使用python、jinja 2和FastAPI建立一个在线商店。当我提交表单,以张贴添加到购物车数据,我收到一个错误
{"detail":[{"loc":["body"],"msg":"value is not a valid dict","type":"type_error.dict"}]}
在swagger UI中,post路由正在运行并发送到postgres数据库。我使用pydantic模型是因为我希望使用req.body和使用jinja 2模板填充index.html上的查询参数。我正在使用post将产品添加到购物车时运行uvicorn控制台中的错误是INFO:127.0.0.1:58872-“POST /checkout HTTP/1.1”422 Unprocessable Entity.我读到dict类型与json数据可能有问题,但我不知道如果数据类型是问题的根源,我可以在哪里改变。
是什么导致了这些错误?
checkout.py
from fastapi import APIRouter,Form, HTTPException, Depends, Request, Body
from fastapi.responses import ORJSONResponse, RedirectResponse
from typing import Annotated
from sqlalchemy.orm import Session
from starlette.templating import Jinja2Templates
import models
from models import Products
from database import engine, SessionLocal
from pydantic import BaseModel, Field
from routers import checkout
from fastapi.templating import Jinja2Templates
router = APIRouter()
models.Base.metadata.create_all(bind=engine)
templates = Jinja2Templates(directory="templates")
#pydanitic request - can be utilized for the post method
class ProductRequest(BaseModel):
product: str
price: int
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
db_dependency = Annotated[Session, Depends(get_db)]
@router.get("/checkout")
async def display_all_checkout():
return {"checkout": "items"}
@router.post("/checkout",status_code=201, response_class=ORJSONResponse)
async def addcheckout(db:db_dependency, request: Request, created_product: ProductRequest):
try:
product_product = request.form['product_product']
product_price=int(request.form['product_price'])
product= db.query(Products).filter(Products.id == id).first()
if product_product and product_price and request.method == 'POST':
DictItems=Products(**created_product.dict())
print(DictItems)
except Exception as e:
print(e)
finally:
return RedirectResponse(url="/product" )
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Store</title>
<link rel="stylesheet" type="text/css" href="{{url_for('static', path='/products/css/base.css')}}">
</head>
<body class="grv-font">
<div class="container">
<h1 class="grv-text__heading--xxlarge">Store</h1>
<h3 class="grv-text__heading--medium">Welcome to the store</h3>
<div class="no-records">Your Cart is Empty</div>
</div>
<div class="shopping-cart">
</div>
<div class="grv-row">
{% for product in product_list %}
<div class="grv-col--xs-2 grv-col--md-4 grv-col--lg-6">
<div class="grid-fill">
<form method="post" action="{{url_for('addcheckout')}}">
<br>
<div class="content grv-card">
<span class="product-name">{{product.product}}</span>
<span class="product-price">${{product.price}}</span>
<div id="add" class="add-to-cart">
<label for="product_id">product_id</label>
<input type="hidden" id="product_id" name="product_id" value="{{product.id}}"/>
<label for="product_product">product_id</label>
<input type="hidden" id="product_product" name="product_product" value="{{product.product}}"/>
<label for="product_price">product_id</label>
<input type="hidden" id="product_price" name="product_price" value="{{product.price}}"/>
<input type="number" class="product-quantity" name="quantity" vlaue="1" min="1"/>
<input type="submit" value="add to cart" class="grv-button--action grv-button--compact"/>
</div>
</div>
</form>
</div>
</div>
{%endfor%}
</div>
<script src="{{url_for('static', path='/products/js/index.js')}}"></script>
</body>
</html>
models.py
from database import Base
from sqlalchemy import Column, Integer, String
class Products(Base):
__tablename__ = 'products'
id = Column(Integer, primary_key=True, index= True)
product=Column(String)
price=Column(Integer)
class Config:
orm_mode = True
1条答案
按热度按时间uqdfh47h1#
问题是您的POST请求期望JSON数据,但实际上您正在发送表单数据。所以FastAPI试图将请求体解析为JSON,但失败了。
要解决此问题,您有两个选择:
1.接受表单数据而不是JSON。您可以通过将路由更改为:
删除
created_product: ProductRequest
参数。然后您可以从request.form
访问表单数据。1.继续接受JSON,但实际上从前端发送JSON。您需要让表单提交JSON而不是常规表单数据。
因此,总的来说,您的选择是:
1.接受表单数据(删除JSON参数)
1.实际上从前端发送JSON以匹配端点所期望的内容。