CodingNic

Databases and Persistence

Building the My To-Read Books Application

Databases and Persistence 60 min read

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:

  1. Unzip the file. You’ll get a folder called book-app.
  2. Open the folder in your code editor.
  3. Open a terminal inside the folder.
  4. 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

  1. Create a new folder called book-app
  2. Open the folder in your code editor
  3. Open a terminal inside the folder

Step 2: Create Virtual Environment

Instructions

  1. Run the command to create a virtual environment

    macOS / Linux

    bash
    python3 -m venv venv
    source venv/bin/activate
    

    Windows

    bash
    python -m venv venv
    venv\Scripts\activate
    
  2. Install required packages:

bash
pip install flask flask-sqlalchemy

Tip: If you’re using the starter, you can install everything with:

bash
pip install -r requirements.txt

Step 3: Create Project Structure (skip if using the starter)

Create the following files and folders:

bash
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:

  1. Import Flask

  2. Create a Flask app

  3. Configure the database:

    • Use SQLite
    • Database name: books.db
  4. Disable SQLALCHEMY_TRACK_MODIFICATIONS

  5. Initialize SQLAlchemy


Expected Outcome

You should have:

  • A Flask app
  • A database connection ready

Step 5: Create Book Model

Instructions

Open models.py and:

  1. Import db from your app
  2. Create a class called Book
  3. 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

  1. Open a Python shell by running this in your terminal:
bash
python
  1. Inside the Python shell, run the following commands:
python
from app import app, db
from models import Book

with app.app_context():
    db.create_all()
  1. Exit the Python shell:
python
exit()

Note: The with app.app_context(): line is important.
Without it, you will get a RuntimeError: Working outside of application context.


Expected Outcome

A file named:

text
books.db

is created in your project folder.


Step 7: Display All Books

Instructions

In app.py:

  1. Import render_template
  2. Import your Book model
  3. Create a route for /

Inside the route:

  1. Retrieve all books from the database
  2. 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.html template

For POST request:

  1. Get form data using request.form.get()

  2. Create a new Book object

  3. Assign all fields:

    • title
    • author
    • genre
    • pages
    • year
    • status
    • cover_url
    • notes
  4. Add the object to the database session

  5. Commit the session

  6. 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:

text
/books/<int:id>

Note: Use <int:id> (not just <id>) so that Flask converts the URL part to an integer automatically.

Inside the route:

  1. Retrieve a book using its ID
  2. If not found, return a 404 error
  3. 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:

text
/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:

  1. Retrieve the book
  2. Update all fields from form data
  3. Commit the changes
  4. 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:

text
/books/<int:id>/delete

Inside the route:

  1. Retrieve the book
  2. Delete it from the database
  3. Commit the changes
  4. 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

bash
python app.py

Open:

text
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 name attributes 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() outside app.app_context()
  • Circular imports between app.py and models.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_URI and SQLALCHEMY_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 name attribute in your HTML form must match the key you read
  • Save with db.session.add(book) then db.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.