Question: 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 # ??? 

Answer: 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 could 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, as explained here, you could change the response status code to status_code=status.HTTP_303_SEE_OTHER, and the issue would 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. If you would like to achieve the same result, 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>