Building the My To-Read Books Application
Building the My To-Read Books Application
In this lesson, you will build the application step by step.
You will not be given full solutions.
Instead, you will follow detailed instructions and implement each part yourself.
If you get stuck, check the Hints Appendix at the end of this lesson.
Starter Code
To save time, download the starter project. It includes the HTML templates,
the stylesheet, and skeleton files for app.py and models.py with TODO
comments matching each step of this lesson.
📦 Download book-app-starter.zip
After downloading:
- Unzip the file. You’ll get a folder called
book-app. - Open the folder in your code editor.
- Open a terminal inside the folder.
- Skip ahead to Step 2 to set up the virtual environment.
Don’t want to use the starter?
You can still build everything from scratch by following the steps below.
Step 1: Create the Project (skip if using the starter)
Instructions
- Create a new folder called
book-app - Open the folder in your code editor
- Open a terminal inside the folder
Step 2: Create Virtual Environment
Instructions
-
Run the command to create a virtual environment
macOS / Linux
python3 -m venv venv source venv/bin/activateWindows
python -m venv venv venv\Scripts\activate -
Install required packages:
pip install flask flask-sqlalchemy
Tip: If you’re using the starter, you can install everything with:
pip install -r requirements.txt
Step 3: Create Project Structure (skip if using the starter)
Create the following files and folders:
book-app/
├── app.py
├── models.py
├── requirements.txt
├── static/
│ └── styles.css
└── templates/
├── base.html
├── index.html
├── detail.html
├── add.html
└── edit.html
Copy your HTML templates into the templates folder.
Step 4: Setup Flask Application
Instructions
In app.py:
-
Import Flask
-
Create a Flask app
-
Configure the database:
- Use SQLite
- Database name:
books.db
-
Disable
SQLALCHEMY_TRACK_MODIFICATIONS -
Initialize SQLAlchemy
Expected Outcome
You should have:
- A Flask app
- A database connection ready
Step 5: Create Book Model
Instructions
Open models.py and:
- Import
dbfrom your app - Create a class called
Book - Make it inherit from
db.Model
Add Fields
Define the following columns:
id
- Type: Integer
- Property: Primary key
title
- Type: String
- Length: 200
- Property: Required (cannot be empty)
author
- Type: String
- Length: 100
- Property: Required
genre
- Type: String
- Length: 50
- Property: Optional
pages
- Type: Integer
- Property: Optional
year
- Type: Integer
- Property: Optional
status
-
Type: String
-
Length: 20
-
Property: Optional
-
Example values:
- “want”
- “reading”
- “finished”
cover_url
- Type: String
- Length: 255
- Property: Optional
notes
- Type: Text
- Property: Optional
Expected Outcome
You should have a complete model that represents a book in the database.
Step 6: Create Database
Instructions
- Open a Python shell by running this in your terminal:
python
- Inside the Python shell, run the following commands:
from app import app, db
from models import Book
with app.app_context():
db.create_all()
- Exit the Python shell:
exit()
Note: The
with app.app_context():line is important.
Without it, you will get aRuntimeError: Working outside of application context.
Expected Outcome
A file named:
books.db
is created in your project folder.
Step 7: Display All Books
Instructions
In app.py:
- Import
render_template - Import your
Bookmodel - Create a route for
/
Inside the route:
- Retrieve all books from the database
- Pass the books to
index.html
Expected Behavior
- When you open the homepage, it loads without errors
- Later, it will display books
Step 8: Add a Book
Instructions
Create a route /add that handles both GET and POST requests.
For GET request:
- Return the
add.htmltemplate
For POST request:
-
Get form data using
request.form.get() -
Create a new
Bookobject -
Assign all fields:
- title
- author
- genre
- pages
- year
- status
- cover_url
- notes
-
Add the object to the database session
-
Commit the session
-
Redirect to the homepage
Expected Behavior
- You can open
/add - You can submit a form
- The app redirects to
/
Step 9: View a Book
Instructions
Create a route:
/books/<int:id>
Note: Use
<int:id>(not just<id>) so that Flask converts the URL part to an integer automatically.
Inside the route:
- Retrieve a book using its ID
- If not found, return a 404 error
- Pass the book to
detail.html
Expected Behavior
- Clicking “View” opens the detail page
- The correct book is displayed
Step 10: Edit a Book
Instructions
Create a route:
/books/<int:id>/edit
This route should handle both GET and POST.
For GET request:
- Retrieve the book
- Pass it to
edit.html - Form should be pre-filled
For POST request:
- Retrieve the book
- Update all fields from form data
- Commit the changes
- Redirect to the detail page
Expected Behavior
- You can edit a book
- Changes are saved
- You are redirected correctly
Step 11: Delete a Book
Instructions
Create a route:
/books/<int:id>/delete
Inside the route:
- Retrieve the book
- Delete it from the database
- Commit the changes
- Redirect to homepage
Expected Behavior
- Clicking delete removes the book
- The list updates
Note: In this lesson, the delete route uses a GET request to keep things simple.
In a real production app, delete actions should use a POST or DELETE method, since GET requests should not change data.
You will learn the proper approach in a later lesson.
Step 12: Run the Application
python app.py
Open:
http://127.0.0.1:5000/
Final Check
Your application should allow you to:
- Add books
- View details
- Edit books
- Delete books
Common Mistakes
- Forgetting to activate the virtual environment
- Missing form
nameattributes in HTML - Not committing database changes (forgetting
db.session.commit()) - Using wrong route URLs (e.g.
<id>instead of<int:id>) - Forgetting to import models
- Running
db.create_all()outsideapp.app_context() - Circular imports between
app.pyandmodels.py
Hints Appendix
If you get stuck on a step, use these hints. Try to write the code yourself first.
Hint for Step 4 — Setup Flask
- Use
Flask(__name__)to create the app - The database URI format is:
sqlite:///books.db - Set the config keys:
SQLALCHEMY_DATABASE_URIandSQLALCHEMY_TRACK_MODIFICATIONS - Initialize with:
db = SQLAlchemy(app)
Hint for Step 5 — Book Model
- Each field uses
db.Column(...) - Common types:
db.Integer,db.String(length),db.Text - Required fields use
nullable=False - The primary key uses
primary_key=True
Hint for Step 7 — Display All Books
- Use
Book.query.all()to fetch every book - Use
render_template("index.html", books=books)to pass data to the template
Hint for Step 8 — Add a Book
- Check the request method with
request.method == "POST" - Read each field with
request.form.get("field_name") - The
nameattribute in your HTML form must match the key you read - Save with
db.session.add(book)thendb.session.commit() - Redirect with
return redirect("/")
Hint for Step 9 — View a Book
- Use
Book.query.get_or_404(id)to fetch one book or return a 404 - Pass it to the template like:
render_template("detail.html", book=book)
Hint for Step 10 — Edit a Book
- Fetch the book first with
get_or_404(id) - For each field, assign the new value:
book.title = request.form.get("title") - Don’t create a new
Book— modify the existing one - Commit with
db.session.commit() - Redirect to
/books/<id>
Hint for Step 11 — Delete a Book
- Fetch the book with
get_or_404(id) - Delete with
db.session.delete(book) - Commit with
db.session.commit() - Redirect to
/
Summary
You built a complete application that:
- Stores data in a database
- Handles user input
- Displays dynamic content
- Supports full CRUD operations
Outcome
You can now:
- Build database-driven applications
- Use Flask with SQLAlchemy
- Structure full web applications
This is a major milestone in your learning journey.