0

I am creating an API using fastAPI, which receives a form from a HTML page, treats it (requiring a few moments) and returns a message saying this task is complete. The way my API is built is:

from cgi import test
from fastapi import FastAPI, Form, Request
from starlette.responses import FileResponse

app = FastAPI()

@app.post("/")
async def swinir_dict_creation(request: Request,taskname: str = Form(...),tasknumber: int = Form(...)):

    args_to_test = {"taskname":taskname, "tasknumber":tasknumber} # dict creation
    print('\n',args_to_test,'\n')
    # my_function_does_some_data_treatment.main(args_to_test)
    # return 'Treating...'
    return 'Super resolution completed! task '+str(args_to_test["tasknumber"])+' of '+args_to_test["taskname"]+' done'

@app.get("/")
async def read_index():
    return FileResponse("index.html")

And my form:

<html>
   <head>
      <h1><b>Super resolution image treatment</b></h1>   
      <body>
        <form action="http://127.0.0.1:8000/" method="post" enctype="multipart/form-data">

            <label for="taskname" style="font-size: 20px">Task name*:</label>
            <input type="text" name="taskname" id="taskname" />
    
            <label for="tasknumber" style="font-size: 20px">Task number*:</label>
            <input type="number" name="tasknumber" id="tasknumber" />

            <b><p style="display:inline"> * Cannot be null</p></b>
            <button type="submit" value="Submit">Start</button>
         </form>
      </body>
   </head>
</html>

So the frontend looks like:

enter image description here

When my treatment is finished, the return of fastAPI's post simply redirects to a page showing only the return message. I was looking for a alternative that would keep the form appearing and showing the message I want below this form, for example this:

enter image description here

I searched in fastAPI documentation about requests, but I haven't found anything that could avoid from not modifying my original HTML page.

  • You’ll need to make an AJAX call to the API using something like the Fetch API. Duplicate of [How can I make an AJAX call without jQuery?](https://stackoverflow.com/questions/8567114/how-can-i-make-an-ajax-call-without-jquery) – esqew Mar 29 '22 at 15:55
  • @esqew, it may be, but the answer I got here was way clearer to solve the problem and moreover it shows how to integrate it with a HTML code. So I'll check 'not duplicate' thinking about future people that might have the same doubt. – brenodacosta Mar 30 '22 at 09:12

1 Answers1

1

You would need to use a Javascript interface/library, such as Fetch API, to make an asynchronous HTTP request. Also, you should use Templates to render and return a TemplateResponse, instead of FileResponse, as shown in your code. Example below:

app.py

from fastapi import FastAPI, Form, Request
from fastapi.templating import Jinja2Templates

app = FastAPI()
templates = Jinja2Templates(directory="templates")

@app.post("/submit")
async def submit(request: Request, taskname: str = Form(...), tasknumber: int = Form(...)):
    return f'Super resolution completed! task {tasknumber} of {taskname} done'

@app.get("/")
async def index(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

templates/index.html

<html>
   <head>
      <script type="text/javascript">
         function submitForm() {
             var formElement = document.getElementById('myForm');
             var data = new FormData(formElement);
             fetch('/submit', {
                   method: 'POST',
                   body: data,
                 })
                 .then(response => response.text())
                 .then(data => {
                   document.getElementById("responseArea").innerHTML = data;
                 })
                 .catch(error => {
                   console.error(error);
                 });
         }
      </script>
   </head>
   <body>
      <h1>Super resolution image treatment</h1>
      <form method="post" id="myForm">
         <label for="taskname" style="font-size: 20px">Task name*:</label>
         <input type="text" name="taskname" id="taskname" />
         <label for="tasknumber" style="font-size: 20px">Task number*:</label>
         <input type="number" name="tasknumber" id="tasknumber" />
         <b><p style="display:inline"> * Cannot be null</p></b>
         <input type="button" value="Start" onclick="submitForm()">
      </form>
      <div id="responseArea"></div>
   </body>
</html>
Chris
  • 4,940
  • 2
  • 7
  • 28