Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python FastAPI "Post Unprocessable Entity" error

Getting error when to submit button

main.py

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from googletrans import Translator

import uvicorn

#from googletrans import Translator
#init
app = FastAPI(debug=True)

templates = Jinja2Templates(directory="template")


#route
@app.get('/')
async def home(request: Request):
        data = {'request': request}
        return templates.TemplateResponse('translates.html', data)


class variable(BaseModel):
    Input_text: str
    trans: str

#def translator(request):
@app.post('/',response_model=variable)
async def trans(request: Request,  form: variable ):

    text = request.get('Input_text')
    lang = request.get('trans')
    # print('text:',text,'lang:',lang)

    # connect the translator
    translator = Translator(service_urls=['translate.googleapis.com'])

    # detect langguage
    dt = translator.detect(text)
    dt2 = dt.lang

    # translate the text
    translated = translator.translate(text, lang)
    tr = translated.text
    data = {
        'request': request,
        'translated': tr
        , 'u_lang': dt2
        , 't_lang': lang}

    return templates.TemplateResponse(data, "translates.html",)


if __name__=="__main__":
   uvicorn.run(app,host="127.0.0.1",port=8000)

Then the HTML code

translate.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Translate</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.js"></script>

</head>
<body>
<div class="ui container">
    <h2>Translation</h2>

<form action="" method="post">
    <br>

<div class="form-input">
    <center><label for="TextareaInput">Enter Text </label></center>
    <center><textarea class="form-control" name="Input_text" id="TextareaInput" rows="3"></textarea></center>
</div>
<div class="ui divider"></div>

<div class="selection list">
  <center><label for="languages">Choose Langguage:</label></center>
  <center><select name="trans" id="languages">
    <option value="en">English</option>
    <option value="ms">Malay</option>
    <option value="zh-cn">Mandarin</option>
    <option value="ko">Korean</option>
      <option value="ja">Japanese</option>
      <option value="vi">Vietnamese</option>
      <option value="th">Thailand</option>
  </select></center>
</div>
<div class="ui divider"></div>

<div>
   <center> <button type="Submit" class="button">Translate</button></center>
</div>
<div class="ui divider"></div>

<div class="form-output">
    <!---<center><textarea class="form-control" id="TextareaOutput" rows="3" value={{translated}} placeholder="Translate..."></textarea></center>-->

    <div class="Output Translation">

        <br><br>
        <h1>Text translated {{u_lang}} from {{t_lang}}</h1>
        <center>
            <h1>{{translated}}</h1>
        </center>
    </div>
</div>
</form>

</div>

</body>
</html>

When I try to button submit these happen ->

{
  "detail": [
    {
      "loc": [
        "body",
        0
      ],
      "msg": "Expecting value: line 1 column 1 (char 0)",
      "type": "value_error.jsondecode",
      "ctx": {
        "msg": "Expecting value",
        "doc": "Input_text=hi&trans=zh-cn",
        "pos": 0,
        "lineno": 1,
        "colno": 1
      }
    }
  ]
}

Pretty sure the error occurs on my BaseModel parameter but I seem can't get it corrected, already search on the internet tho.

like image 540
Fahmi Avatar asked Dec 03 '20 04:12

Fahmi


People also ask

What is 422 Unprocessable Entity in fastapi 422 response?

The body of FastAPIs 422 response contains an error message telling you exactly which part of your request doesn't match the expected format. According to MDN here , a 422 Unprocessable Entity means that the information of the request could not be processed.

Why is my fastapi route parameter key missing?

The 1st error says key is missing from the query, meaning the route parameter key value "Baz" was not in the request body and FastAPI tried to look for it from the query parameters (see the FastAPI docs on Request body + path + query parameters ).

What is error the422 Unprocessable Entity?

The422 Unprocessable Entitystatus code is a client-side error. It belongs to the HTTP response status codes in the 4xx category, called client error responses . In short, 4xx errors indicate that the page you requested wasn't found, and something is wrong with the request.

How do I use HTTP exception in fastapi?

HTTPException This function ships with the fastapi module. Therefore, in order to start using it, we just need to import it. Once imported, it can be used by calling it along with the “raise” keyword. Looking a little closer at what we are passing to the exception, there is the “status_code” and “detail”.


2 Answers

When you use pydantic models for a request body parameters, FastAPI interprets them as json objects:

With just that Python type declaration, FastAPI will:

  • Read the body of the request as JSON.
  • Convert the corresponding types (if needed).
  • Validate the data...

But HTML forms are sent to the server not in the form of json, but in a special x-www-form-urlencoded format (more info here), so to read the form values, you need to use the Form parameters, like so:

@app.post("/")
async def path_operation(Input_text: str = Form(...), trans: str = Form(...)):
    return {"Input_text": Input_text, "trans": trans}
like image 131
alex_noname Avatar answered Oct 19 '22 06:10

alex_noname


You can use Pydantic models, but you need to create a workaround like this, it expects a Body by default, so we are changing the signature of the Fields by wrapping the Pydantic Model.

from fastapi import Form, Depends


def form_body(cls):
    cls.__signature__ = cls.__signature__.replace(
        parameters=[
            arg.replace(default=Form(...))
            for arg in cls.__signature__.parameters.values()
        ]
    )
    return cls


@form_body
class variable(BaseModel):
    Input_text: str
    trans: str

Then you can start using it like this

from fastapi import FastAPI, Form, Depends
from pydantic import BaseModel


app = FastAPI(debug=True)


def form_body(cls):
    cls.__signature__ = cls.__signature__.replace(
        parameters=[
            arg.replace(default=Form(...))
            for arg in cls.__signature__.parameters.values()
        ]
    )
    return cls


@form_body
class variable(BaseModel):
    Input_text: str
    trans: str


@app.post("/", response_model=variable)
async def trans(form: variable = Depends(variable)):

    return form
like image 1
Yagiz Degirmenci Avatar answered Oct 19 '22 05:10

Yagiz Degirmenci