Lesson 50 of 55 · javascript
Project: Building a Todo App
Duration: 30 mins
Project: Building a Todo App
In this capstone project you’ll combine many of the concepts you’ve learned: Flask routes, SQLite persistence, HTML templating with Jinja2, and basic CRUD operations.
Steps Overview
- Initialize the Flask app and configure a SQLite database.
- Create a
taskstable with columnsid(INTEGER PK) anddescription(TEXT). - Define routes to list tasks, add a new task, and delete a task.
- Render the UI using a simple Jinja2 template (
templates/index.html). - (Optional) Add a bit of CSS for a cleaner look.
Starter Skeleton
from flask import Flask, render_template, request, redirect, url_for
import sqlite3
app = Flask(__name__)
def get_db():
conn = sqlite3.connect('todo.db')
conn.row_factory = sqlite3.Row # Access columns by name
return conn
# Initialise the DB (run once)
def init_db():
with get_db() as db:
db.execute('CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY, description TEXT NOT NULL)')
@app.route('/')
def index():
db = get_db()
tasks = db.execute('SELECT * FROM tasks').fetchall()
return render_template('index.html', tasks=tasks)
@app.route('/add', methods=['POST'])
def add_task():
desc = request.form['description']
if desc:
db = get_db()
db.execute('INSERT INTO tasks (description) VALUES (?)', (desc,))
db.commit()
return redirect(url_for('index'))
@app.route('/delete/<int:task_id>', methods=['POST'])
def delete_task(task_id):
db = get_db()
db.execute('DELETE FROM tasks WHERE id = ?', (task_id,))
db.commit()
return redirect(url_for('index'))
if __name__ == '__main__':
init_db()
app.run(debug=True)
templates/index.html (very simple)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Todo App</title>
</head>
<body>
<h1>My Todo List</h1>
<form action="{{ url_for('add_task') }}" method="post">
<input type="text" name="description" placeholder="New task" required>
<button type="submit">Add</button>
</form>
<ul>
{% for task in tasks %}
<li>
{{ task['description'] }}
<form action="{{ url_for('delete_task', task_id=task['id']) }}" method="post" style="display:inline;">
<button type="submit">Delete</button>
</form>
</li>
{% else %}
<li>No tasks yet!</li>
{% endfor %}
</ul>
</body>
</html>
Run the app, open http://127.0.0.1:5000/ in your browser, and start adding and removing tasks. This project ties together Flask routing, SQLite CRUD, Jinja2 templating, and form handling. Happy coding! 🎉