Project: Todo Full-Stack App
Introduction
This project combines user accounts and personal todo lists in one Flask app—registration, login, CRUD on todos, and database migrations. It is the track’s full-stack capstone: factory pattern, Flask-Login, Flask-WTF, SQLAlchemy, Migrate, and pytest together.
Prerequisites
- User Authentication With Flask-Login
- Forms and Flask-WTF
- Database Migrations With Flask-Migrate
- Testing Flask Applications
Project Goals
- Users register and log in (hashed passwords)
- Each user sees only their todos
- Create, complete, and delete todos
- WTForms for HTML UI (primary mode)
- pytest covers auth and todo CRUD
Step 1: Models
app/models.py:
Migrate:
flask db migrate -m "Users and todos"
flask db upgradeStep 2: Auth Blueprint
Registration and login from Flask-Login chapter—redirect to /todos after login.
login_manager.login_view = "auth.login"
Step 3: Todo Routes
app/todos/routes.py:
Code explanation:
filter_by(user_id=current_user.id)prevents accessing other users’ todosfirst_or_404()returns 404 if id wrong or not owned
Step 4: Todo Form
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired, Length
class TodoForm(FlaskForm):
title = StringField("New todo", validators=[DataRequired(), Length(max=200)])
submit = SubmitField("Add")templates/todos/list.html:
For inline toggle/delete forms without TodoForm, expose csrf_token() in template config or use separate small WTF forms.
Step 5: JSON API Mode (Optional)
Add /api/v1/todos returning JSON for the same queries—reuse logic in a service function get_user_todos(user_id) called from HTML and API routes. Pick one primary UI for the tutorial; JSON is optional stretch.
Step 6: pytest
tests/test_todos.py:
Use auth_client fixture from testing chapter.
Verification Checklist
- Register → login → see empty todo list
- Add, toggle, delete todos
- Logout blocks
/todos - User A cannot delete User B’s todo (404)
- Migrations apply cleanly on fresh DB
-
pytestgreen
FAQ
CSRF on inline delete forms?
Each POST form needs CSRF—hidden_tag() or csrf_token().
Due dates and priorities?
Add columns + migration—good schema exercise.
HTMX instead of full reload?
Replace forms with HTMX hx-post—same routes.
Mobile app?
Expose JSON API + JWT from REST project patterns.
Password reset?
Email token flow—requires Flask-Mail and async queue.
Deploy?
Next chapter—production deployment project.