📋 Setting Up the To-Do Page in Our Full-Stack FastAPI App
In this step, we’re creating the main dashboard of our application: the To-Do page. This page will display all tasks for a logged-in user and allow them to add, edit, delete, and mark tasks as complete.
1️⃣ Update todos.py Router
Imports
At the top of todos.py, make sure to import:
from fastapi import Request, Depends, status
from fastapi.templating import Jinja2Templates
from starlette.responses import RedirectResponseTemplates Variable
templates = Jinja2Templates(directory="TodoApp/templates")2️⃣ Redirect Function
We need a helper function to redirect unauthenticated users to the login page:
def redirect_to_login():
redirect_response = RedirectResponse(url="/auth/login-page", status_code=status.HTTP_302_FOUND)
redirect_response.delete_cookie(key="access_token") # Remove token if it exists
return redirect_response3️⃣ To-Do Page Endpoint
@router.get("/todo-page")
async def render_todo_page(request: Request, db=Depends(get_db)):
try:
# Get current user using JWT from cookies
user = await get_current_user(request.cookies.get("access_token"))
if not user:
return redirect_to_login()
# Fetch all todos for this user
todos = db.query(Todos).filter(Todos.owner_id == user.id).all()
return templates.TemplateResponse(
"todo.html",
{"request": request, "todos": todos, "user": user}
)
except:
return redirect_to_login()✅ Notes:
get_current_useruses the JWT in cookies to verify identity.If the JWT is invalid or missing, the user is redirected to login.
todoscontains all tasks for the logged-in user.
4️⃣ Create todo.html Template
Inside templates, create todo.html and paste the code below inside.
{% include "layout.html" %}
<div class="container">
<div class="card text-center">
<div class="card-header">Your To-Dos</div>
<div class="card-body">
<h5 class="card-title">List of Your To-Dos</h5>
<p class="card-text">Information regarding tasks that need completion</p>
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Info</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{% for todo in todos %}
{% if not todo.complete %}
<tr class="pointer">
<td>{{ loop.index }}</td>
<td>{{ todo.title }}</td>
<td>
<button type="button" class="btn btn-info"
onclick="window.location.href='/edit-todo-page/{{ todo.id }}'">
Edit
</button>
</td>
</tr>
{% else %}
<tr class="pointer alert alert-success">
<td>{{ loop.index }}</td>
<td class="strikethrough">{{ todo.title }}</td>
<td>
<button type="button" class="btn btn-info"
onclick="window.location.href='/edit-todo-page/{{ todo.id }}'">
Edit
</button>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<a href="/add-todo-page" class="btn btn-primary">Add a New To-Do</a>
</div>
</div>
</div>✅ Features:
Table view for all user’s todos.
Strikethrough completed tasks (
todo.complete == True).Edit buttons redirect to the edit page for each task.
Add button to create a new to-do.
5️⃣ Testing the Page
Start the application:
uvicorn TodoApp.main:app --reloadGo to:
/auth/login-pageand log in.You’ll see your to-dos listed.
If there are no to-dos yet, you can create some via
/docsor future add-todo page.Completed tasks appear with a green alert and strikethrough.
Unauthenticated access redirects to login.
✅ Summary
We added a To-Do page template (
todo.html).Connected it with FastAPI endpoint
/todo-page.Implemented user-based filtering using JWT in cookies.
Displayed todos in a table with conditional formatting.
Redirects unauthenticated users to login.
Next up: implementing logout functionality to safely remove cookies and log out users.