Reputation: 41
When I use GET
request to send data to the server it works fine, but when use POST
request it throws "422 Unprocessable Entity" error.
This is my Ajax request code:
var newName = "Bhanuka";
//do your own request an handle the results
$.ajax({
type: "post",
url: "/names/",
data: {d:newName},
dataType: 'json',
success: function(data){
console.log(data);
}
});
and this is my FastAPI server side code:
from fastapi import FastAPI, Request,Body
from pydantic import BaseModel
from fastapi.templating import Jinja2Templates
from fastapi.encoders import jsonable_encoder
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/items/{id}")
async def read_item(request: Request, id: str):
return templates.TemplateResponse("item.html", {"request": request, "id": id})
@app.post("/names/")
async def create_item(d:str):
return d
@app.get("/items11/{item_id}")
def read_item22(item_id: int, q: str ):
return {"item_id": item_id, "q": q}
Upvotes: 4
Views: 17445
Reputation: 34560
In short, the endpoint (/names/
) in your API—in the way that is defined—expects a string query parameter d
, but your client (Ajax request) sends JSON
payload. Hence, the 422 Unprocessable Entity
error. To receive the data in JSON
format, one needs to create a Pydantic BaseModel as follows:
server side
class Data(BaseModel):
name: str
@app.post("/names/")
def create_item(data: Data):
recv_data = data.dict()
return recv_data['name']
Alternatively, one could use the Body(...)
field—if only a single body parameter is required, use Body(..., embed=True) instead, as shown below:
@app.post("/names/")
def create_item(name: str = Body(..., embed=True)):
return name
The client should then look like this (no matter which of the above you use):
client side
$.ajax({
type: "post",
url: "/names/",
data: '{"name": "Bhanuka"}',
contentType: "application/json",
dataType: 'json',
success: function(data) {
console.log(data);
}
});
Please have a look at this answer and this answer for more details and examples.
Upvotes: 0
Reputation: 771
The 422 Unprocessable Entity
error because of ContentType
is incorrect. The FastAPI need ContentType = application/json
to parse request body.
But the default ContentType for $.ajax is application/x-www-form-urlencoded; charset=UTF-8
. For detail link
contentType (default: 'application/x-www-form-urlencoded; charset=UTF-8') Type: Boolean or String When sending data to the server, use this content type. Default is "application/x-www-form-urlencoded; charset=UTF-8", which is fine for most cases. If you explicitly pass in a content-type to $.ajax(), then it is always sent to the server (even if no data is sent). As of jQuery 1.6 you can pass false to tell jQuery to not set any content type header. Note: The W3C XMLHttpRequest specification dictates that the charset is always UTF-8; specifying another charset will not force the browser to change the encoding. Note: For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.
So, you should set ContentType Header for the request as below:
var newName = "Bhanuka";
//do your own request an handle the results
$.ajax({
type: "post",
url: "/names/",
data: {d:newName},
dataType: 'json',
contentType: 'application/json',
success: function(data){
console.log(data);
}
});
Upvotes: 0
Reputation: 11
There was this trouble on me a few days ago.
I solved that with an article, reference. So; while get, delete etc. methods working good, post method dont! I've wrote Form class for parsing FormData coming from fastapi>Request.
class Form:
def __init__(self, form: FormData, model: BaseModel):
for k, v in form.items():
if k[0].isdigit():
k = f"_{k}"
setattr(model, str(k), v)
self.form = model
Then I've modified my own decorator as like that:
@app.post("/login")
async def check_login(request: Request):
form = await request.form()
model: LoginModel = Form(form, LoginModel).form
Then I can access the posted data, model.name
etc.
Upvotes: 1
Reputation: 101
It is because the data you are sending is json. and the POST request api is expecting str.
If the formats doesn't match during the api calls, it raises the Unprocessable Entity error.
You can deal it using
Well, coming to the first case, 1.Request: you can use request with curl
curl -i -d "param1=value1¶m2=value2" http://localhost:8000/check
to the below code for example:
from fastapi import FastAPI, Request
from fastapi.encoders import jsonable_encoder
app = FastAPI()
@app.post('/check')
async def check(request: Request):
da = await request.form()
da = jsonable_encoder(da)
print(da)
return da
Upvotes: 2
Reputation: 107
A function parameters can be defined as in 3 types like path , singular types and model. Here you call the method using a JSON
body and therefore it is likely a model
parameter. Therefore in your code , define your input parameter as a model
parameter.
Example -
from pydantic import BaseModel
from fastapi import FastAPI
app = FastAPI()
class Data(BaseModel):
user: str
@app.post("/names/")
def main(input: Data):
return input
Then you can call this as
$.ajax({
type: "post",
url: "/names/",
data: "{'user':'kamal'}",
contentType: "application/json",
dataType: 'json',
success: function(data)
{ console.log(data);
}});
Upvotes: 1