6

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.

1
  • ok turn out i need to put context={} on return example return templates.TemplateResponse('translates.html', context=data) n for post Commented Dec 16, 2020 at 7:38

2 Answers 2

1

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}
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.