How to redirect the user back to the home page using FastAPI, after submitting an HTML form?
Asked Answered
H

1

4

I have a page with a table of students. I added a button that allows you to add a new row to the table. To do this, I redirect the user to a page with input forms.

The problem is that after submitting the completed forms, the user goes to a new empty page. How to transfer data in completed forms and redirect the user back to the table?

I just started learning web programming, so I decided to first make an implementation without using AJAX technologies.

Code:

from fastapi import FastAPI, Form
from fastapi.responses import Response

import json
from jinja2 import Template

app = FastAPI()


# The page with the table
@app.get('/')  
def index():
    students = get_students()  # Get a list of students
    with open('templates/students.html', 'r', encoding='utf-8') as file:
        html = file.read()
    template = Template(html)  # Creating a template with a table

    # Loading a template
    return Response(template.render(students=students), media_type='text/html')


# Page with forms for adding a new entry
@app.get('/add_student')
def add_student_page():
    with open('templates/add_student.html', 'r', encoding='utf-8') as file:
        html = file.read()

    # Loading a page
    return Response(html, media_type='text/html')


# Processing forms and adding a new entry
@app.post('/add')
def add(name: str = Form(...), surname: str = Form(...), _class: str = Form(...)):
    add_student(name, surname, _class)  # Adding student data
    # ???
Harberd answered 13/1, 2022 at 1:41 Comment(2)
It turns out that after clicking the "Add" button, the data from the form is sent to the /add method and the user goes to the same page, which is empty.Harberd
And I need the data from the form to be sent to /add, and the user goes to the main page.Harberd
L
5

To start with, in cases where you return Jinja2 templates, you should return a TemplateResponse, as shown in the documentation. To redirect the user to a specific page, you can use RedirectResponse. Since you do that through a POST (and not GET) method, as shown in your example, a 405 (Method Not Allowed) error would be thrown. However, thanks to @tiangolo, you can change the response status code to status_code=status.HTTP_303_SEE_OTHER, and the issue will then be resolved (please have a look at this answer and this answer for more details). A working example is given below.

In case you needed to pass additional path and/or query parameters to your endpoint, please have a look at this and this answer as well.

In case you had to do the same, using Fetch API instead of HTML <form>, please have a look at this answer.

Working Example

app.py

from fastapi import FastAPI, Request, Form, status
from fastapi.templating import Jinja2Templates
from fastapi.responses import RedirectResponse

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

# replace with your own get_students() method
def get_students():
    return ["a", "b", "c"]

@app.post('/add')
async def add(request: Request, name: str = Form(...), surname: str = Form(...), _class: str = Form(...)):
    # add_student(name, surname, _class)  # Adding student data
    redirect_url = request.url_for('index')    
    return RedirectResponse(redirect_url, status_code=status.HTTP_303_SEE_OTHER)    

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

@app.get('/')
async def index(request: Request):
    students = get_students()  # Get a list of students
    return templates.TemplateResponse("index.html", {"request": request, "students": students})

templates/index.html

<!DOCTYPE html>
<html>
   <body>
      <h1>Students: {{ students }}</h1>
   </body>
</html>

templates/add_student.html

<!DOCTYPE html>
<html>
   <body>
      <form action="http://127.0.0.1:8000/add" method="POST">
         name : <input type="text" name="name"><br>
         surname : <input type="text" name="surname"><br>
         class : <input type="text" name="_class"><br>
         <input type="submit" value="submit">
      </form>
   </body>
</html>
Lindholm answered 13/1, 2022 at 7:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.