2

I have made up the post call and render the jinja2 template of login_form.html

main.py:

from fastapi import FastAPI, Response, status, HTTPException, Depends
import hashlib
from fastapi import APIRouter, Form
from pydantic import BaseModel
from fastapi.staticfiles import StaticFiles
from fastapi import Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

app = FastAPI()

templates = Jinja2Templates(directory="templates")


@app.post("/",response_class=HTMLResponse)
async def login_form(
    request: Request, uname: str = Form(...), passcode: str = Form(...)
):
    print(uname, passcode)
    return templates.TemplateResponse(
        "auth/login_form.html", {"request": request,"result": "res"}
    )

login_form.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Login Form</title>
    </head>
<body>
<h1>Login Form</h1>
<form method="post">
<h5>Username</h5>
<input type="text" name="uname" placeholder="username"></input>
<h5>Password</h5>
<input name="passcode" placeholder="password" type="text"></input>
<input type="submit"></input>
</form>

<p>{{result}}</p>
</body>
</html>

When I load the page on web browser I get:

{"detail":"Method Not Allowed"}

loading the webpage of

Paul P
  • 3,346
  • 2
  • 12
  • 26
Abubakar
  • 43
  • 5
  • Opening it from browser is a GET request, instead you declared a POST one – Federico Provenziani Dec 27 '21 at 09:59
  • @FedericoProvenziani yes but i have seen the jinja2 and fastAPI tutorials that POST requests open like this because it return the html Page at the end – Abubakar Dec 27 '21 at 10:03
  • Sorry, seeing the image and reading your words i thought you tried to access the page from a direct request instead of submitting the form – Federico Provenziani Dec 27 '21 at 10:07
  • I still think @FedericoProvenziani is correct; where is the GET endpoint that displays the template? Since you're not doing anything with the template in the POST endpoint, it seems like that was meant to be a regular GET endpoint? – MatsLindh Dec 27 '21 at 11:33
  • Please have a look at related answers [here](https://stackoverflow.com/a/75715292/17865804), [here](https://stackoverflow.com/a/70693108/17865804) and [here](https://stackoverflow.com/a/71414202/17865804), as well as [here](https://stackoverflow.com/a/73359311/17865804), [here](https://stackoverflow.com/a/71665594/17865804) and [here](https://stackoverflow.com/a/70640522/17865804) – Chris Mar 17 '23 at 06:38

2 Answers2

1

You need two routes first get the template then make post:

@app.get("/")
@app.post("/")
Julia Meshcheryakova
  • 3,162
  • 3
  • 22
  • 42
Mehdi
  • 11
  • 2
0

If you want this to work in the browser, login_form() will have to be a GET endpoint.

If you've seen examples using POST with FastAPI, that's probably because that was for building an API rather than a web app (maybe Starlette is what you're actually looking for).

In order to make your solution work in the browser (with FastAPI) you can add another endpoint (which I'm calling POST /handle-form). You will also have to adapt your login_form.html template (see below).

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)
async def login_form(request: Request):
    return templates.TemplateResponse(
        "auth/login_form.html", {"request": request, "result": "res"}
    )

@app.post("/handle-form")
async def handle_form(
    request: Request,
    uname: str = Form(...),
    passcode: str = Form(...),
):
    print(uname, passcode)

The only change to login_form.html is adding action="handle-form" to the form tag, where handle-form is the the path to the endpoint to post the form data to:

...
<form action="handle-form" method="post">
...

It renders like this:

enter image description here

Once you've entered the username and password and pressed Submit, uname and passcode will be sent to handle_form().

Paul P
  • 3,346
  • 2
  • 12
  • 26