How to submit data using HTML in the frontend and get the results from FastAPI backend?

Question:

I am using FastAPI for the backend and HTML/CSS for the frontend. I want to click the button and get the wanted value in return (mt means when I put node1 and node2 it gets me its prediction from the JSON array.

This is my code:

This is the data list

prediction_data = [
  { "node1": 0, "node2": 1, "pred": 0},
  { "node1": 0, "node2": 476, "pred":0.352956 },
  { "node1": 0, "node2": 494, "pred":0.769988 },
  { "node1": 1, "node2": 505, "pred":0.463901 },
  { "node1": 9, "node2": 68 , "pred":1.238807},
  { "node1": 15, "node2": 408, "pred":0.204171 },
  { "node1": 18, "node2":549 , "pred":0.204171 },
  { "node1": 60, "node2": 227, "pred":0.204171 },
  { "node1": 199, "node2": 220, "pred":0.245246 },
  { "node1": 170, "node2": 570, "pred":0.509272 },
  { "node1": 148, "node2": 570, "pred":0.204171 },
  { "node1": 151, "node2": 384, "pred":0.204114 },
  { "node1": 232, "node2": 337, "pred":0.285999 },
  { "node1": 446, "node2": 509, "pred":0.291206 },
  { "node1": 510, "node2":576 , "pred":0.495378 },
  { "node1": 571, "node2":589 , "pred":0 },
  { "node1": 585, "node2":596 , "pred":0.245243 },
  { "node1": 446, "node2":509 , "pred":0.291206 },
  { "node1": 375, "node2":383 , "pred":0.46390 },
  { "node1": 461, "node2":462 , "pred":0 }
    ]

This the getter function of the wanted value

# Prediction
@app.get("/prediction/{node1,node2}", response_class=HTMLResponse)
async def gets(request: Request, node1: int, node2: int):
    matching = list(filter(lambda x: x['node1'] == node1 and x['node2'] == node2, prediction_data))
    mt = matching[0]['pred'] if matching else None
    return templates.TemplateResponse("Interface.html", {"request": request, "mt": mt})

This is the interface


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Link Prediction</title>
    <link href="{{ url_for('static', path='/style.css') }}" rel="stylesheet">
</head>

<body>
    <div class="container" >
        <h1>Link Prediction </h1>
        <h2>In Social Network</h2>
        <form class="form" action="#">
          <fieldset class="form-fieldset ui-input __first">
            <input type="number" id="Node1" tabindex="0" /> {{node1}}
            <label for="Node1">
              <span data-text="Node 1">Node 1</span>
            </label>
          </fieldset>
          
          <fieldset class="form-fieldset ui-input __second">
            <input  type="number" id="Node2" tabindex="0" /> {{node2}}
            <label for="Node2">
              <span data-text="Node 2">Node 2 </span>
            </label>
          </fieldset>

          <div class="form-footer">
            <button  onclick="myfunctionName(Node1, Node2)" class="btn">Predict Now</button>
          </div>

          <script type="text/javascript">
              
              function myfunctionName( n1,n2 ){
          
                  document.getElementById("Node1").innerHTML += n1;
                  document.getElementById("Node2").innerHTML += n2;
                  document.getElementById("Prediction") = mt;
              }
          
          </script>

<fieldset class="form-fieldset ui-input __third">
    <input type="text" id="Prediction" readonly/> {{mt}}
    <label for="Prediction">
      <span data-text="Prediction Result" >Prediction Result</span>
    </label>
  </fieldset>
          
        </form>
      </div>
</body>
</html>


Asked By: tous

||

Answers:

To start with, you should have a look at how Path parameters work in FastAPI. The following in your code @app.get("/prediction/{node1,node2} is not a valid route for passing path parameters. It will instead be recognised as a single path name. You can verify this by opening Swagger UI
at http://127.0.0.1:8000/docs, which shows that the endpoint expects node1 and node2 to be query params, not path params. When submitting form data, one should use Form fields for that purpose, and POST HTTP method (your endpoint should be using @app.post())—browsers cache GET requests (i.e., saved in browser’s history), thus making them less secure compared to POST—have a look at this detailed answer, as well as this answer. If you still, however, need this to be a GET request, you can use a GET operation @app.get() in your API, as well as define the method for your HTML form being method="GET" (but wouldn’t recommend it).

Backend:

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

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

@app.get('/', response_class=HTMLResponse)
def main(request: Request):
    return templates.TemplateResponse('predict.html', {'request': request})

@app.post('/predict', response_class=HTMLResponse)
def predict(request: Request, node1: int = Form(...), node2: int = Form(...)):
    matching = list(filter(lambda x: x['node1'] == node1 and x['node2'] == node2, prediction_data))
    mt = matching[0]['pred'] if matching else None
    return templates.TemplateResponse("predict.html", {"request": request, "node1": node1, "node2": node2, "mt": mt})

Frontend template (i.e., predict.html in your case):

<!DOCTYPE html>
<html lang="en">
   <body>
      <h1>Link Prediction </h1>
      <h2>In Social Network</h2>
      <form method="POST" action="/predict" id="myForm">
         node1 : <input type="text" name="node1" value={{node1}}> <br>
         node2 : <input type="text" name="node2" value={{node2}}><br>
         <input type="submit" value="Predict" >
      </form>
      Prediction Result: <b>{{mt}}</b>
   </body>
</html>
Answered By: Chris
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.