Using Databases from Applications

Project Checkpoint


In the regular chapters of this part, the examples and exercises focused on the tags table. You added functionality for listing tags, showing the newest tag, creating tags, deleting tags, and updating one chosen tag, and all of the user-input queries used the safe parameterized t-string pattern.

In this part’s project checkpoint, you apply those same patterns to the existing decks feature. The project already has a small read flow for decks; now, you turn it into a full CRUD flow.

Goal

Implement one-table CRUD functionality for decks through the web application.

By the end of this step, the project should have the following visible functionality:

  • a user can read deck data on /decks,
  • a user can read the newest deck on /decks/newest,
  • a user can create one new deck from a form,
  • a user can edit one chosen deck,
  • and a user can delete one chosen deck.

Suggested Sequence

Approach this milestone by extending the functionality one step at a time.

  1. In app/main.py, keep the existing GET /decks route working.
  2. Keep the existing GET /decks/newest route working.
  3. Add a simple create form to app/templates/decks.html.
  4. Add the matching POST route that inserts one new deck and redirects back to /decks. Use a parameterized t-string, exactly as in the tag examples.
  5. Add an Edit link on each deck row on /decks.
  6. Add a GET /decks/{deck_id}/edit route that loads one chosen deck for editing.
  7. Add one template for the edit form.
  8. Add the matching POST route that updates the chosen deck and redirects back to /decks.
  9. Add a Delete deck button for one chosen deck on /decks.
  10. Add the matching POST route that deletes that one deck and redirects back to /decks.
  11. If you want, add a shared base.html template and stable navigation links after the visible CRUD flow is already working.

That order matters. If the list page breaks while forms and edit routes are being added at the same time, it becomes much harder to tell whether the problem is in the route, the template, or the SQL.

Use the existing render() helper from the walking skeleton consistently, the same way the chapter-level tag routes do.

One useful way to think about this milestone is to trace one full create flow:

  1. the browser shows a form on /decks,
  2. the user submits the form,
  3. FastAPI receives a POST request,
  4. the route reads the submitted values,
  5. a parameterized INSERT query stores the new row,
  6. the route redirects back to /decks,
  7. the list route runs its SELECT,
  8. and the template renders the updated list.

If you can explain that sequence for your own code, the create part of the milestone is in good shape. The same kind of trace can then be applied to the edit and delete flows.

Common pitfalls
  • Building SQL strings directly from input instead of using the t-string form.
  • Dropping or forgetting the t prefix and leaving an f-string that only looks parameterized.
  • Forgetting to redirect after a successful write.
  • Updating or deleting the wrong row because the identifier was not passed carefully.
  • Putting action pages such as edit or delete into the top-level navigation.
  • Trying to add multi-table features before the one-table flow is solid.

Project Checkpoint

The embedded checkpoint below contains the exact tested labels, return instructions, and grading requirements.

If you also want to keep the project organized while you build it, you can reuse the Chapter 9 ideas after the required CRUD flow is complete.

Project checkpoint: deck CRUD

0 / 40 points

Return the Part 3 checkpoint of the databases course project as a zip. The returned project must continue the Part 2 overarching project and add deck CRUD functionality through the web application. The grading setup provides PostgreSQL, applies your SQL migrations, starts the FastAPI application, and then checks the visible deck behavior through the browser.

This checkpoint focuses on deck CRUD behavior. You may keep using ideas from Chapter 9, such as a shared base.html template, but the grader does not require a specific code organization pattern.

The root of the returned zip must contain:

  • requirements.txt
  • the folder app
  • the folder migrations

You may also include convenience files such as compose.yaml, a Dockerfile, and a startup script for local development. These are useful for your own workflow, but the grader does not depend on them.

The grader checks the following:

  • The application starts successfully from a clean database using only the SQL files in migrations.
  • The application exposes a FastAPI app as app in app/main.py.
  • The application uses DATABASE_URL for the PostgreSQL connection.
  • The existing /decks page still works and shows the deck rows from the database.
  • The existing /decks/newest page still works and shows the newest deck.
  • The /decks page includes a create form with the labels Deck name and Description, and the submit button text Create deck.
  • The /decks page includes an Edit link for each deck row. That link must lead to /decks/{deck_id}/edit for the chosen deck.
  • The /decks page includes a Delete deck button for each deck row.
  • The edit page for a chosen deck includes the heading Edit Deck, the labels Deck name and Description, and the submit button text Save deck. The form content is pre-filled with the existing values for that deck, and saving the edit updates the visible deck list.
  • A user can create a new deck, update a chosen deck, and delete a chosen deck through the browser.

Return the project as a zip so that the root of the zip contains the files and folders listed above, not an extra enclosing project directory.