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

5
  • Opening it from browser is a GET request, instead you declared a POST one Commented Dec 27, 2021 at 9: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 Commented Dec 27, 2021 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 Commented Dec 27, 2021 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? Commented Dec 27, 2021 at 11:33
  • Please have a look at related answers here, here and here, as well as here, here and here Commented Mar 17, 2023 at 6:38

2 Answers 2

1

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

@app.get("/")
@app.post("/")
Sign up to request clarification or add additional context in comments.

Comments

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().

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.