TDM 40200: Project 6 — 2023

Motivation: Dashboards are everywhere — many of our corporate partners' projects are to build dashboards (or dashboard variants)! Dashboards are used to interactively visualize some set of data. Dashboards can be used to display, add, remove, filter, or complete some customized operation to data. Ultimately, a dashboard is really a website focused on displaying data. Dashboards are so popular, there are entire frameworks designed around making them with less effort, faster. Two of the more popular examples of such frameworks are shiny (in R) and dash (in Python). While these tools are incredibly useful, it can be very beneficial to take a step back and build a dashboard (or website) from scratch (we are going to utilize many powerfuly packages and tools that make this far from "scratch", but it will still be more from scratch than those dashboard frameworks).

Context: This is the fifth in a series of projects focused around slowly building a dashboard. Students will have the opportunity to: create a backend (API) using fastapi, connect the backend to a database using aiosql, use the jinja2 templating engine to create a frontend, use htmx to add "reactivity" to the frontend, create and use forms to insert data into the database, containerize the application so it can be deployed anywhere, and deploy the application to a cloud provider. Each week the project will build on the previous week, however, each week will be self-contained. This means that you can complete the project in any order, and if you miss a week, you can still complete the following project using the provided starting point.

Scope: Python, dashboards

Learning Objectives
  • Continue to develop skills and techniques using fastapi to build a backend.

  • Learn how to use pydantic for data validation and type hints.

  • Learn how fastapi and pydantic work together to create endpoints that validate data and return typed responses.

  • Create a directory structure to assemble a fastapi backend.

Make sure to read about, and use the template found here, and the important information about projects submissions here.


The following questions will use the following dataset(s):

  • /anvil/projects/tdm/data/movies_and_tv/imdb.db


Interested in being a TA? Please apply:

Question 1

Create a directory in your $SCRATCH directory called imdb. This will be the "monorepo" that holds your source code for your dashboard — the frontend, the backend, and any other assets we may end up with. Create all the empty files and folders so your directory structure looks like the following.

project directory structure
├── backend
│   ├── api
│   │   ├──
│   │   ├──
│   │   ├── imdb.db
│   │   ├──
│   │   └── queries.sql
│   ├── pyproject.toml
│   ├──
│   └── templates
├── frontend

4 directories, 8 files

Once complete, demonstrate you’ve created everything properly by running the following in Jupyter Notebook cell.


tree $SCRATCH/imdb
Items to submit
  • Code used to solve this problem.

  • Output from running the code.

Question 2

Okay! You are all set now. You have a sane project structure, and you (hopefully) learned all you needed to perform this next task.

First, we will go ahead and give you the contents of

import os
import aiosql
import sqlite3
from dotenv import load_dotenv
from pathlib import Path


database_path = Path(__file__).parents[0] / "imdb.db"
queries = aiosql.from_path(Path(__file__).parents[0] / "queries.sql", "sqlite3")

That way, from another Python module, you can import and use database_path and queries to interact with the database.

from .database import database_path, queries

Implement you backend and create the following endpoints in your file:

  1. GET /titles/{title_id} — returns the title information as a Title object for the Title with the given title_id.

  2. GET /cast/{title_id} — returns the cast information as a Cast object for the Title with the given title_id.

  3. GET /people/{person_id} — returns the person information as a Person object for the Person with the given person_id.

Fill in the file with the following models: Title, Cast, CastMember, Work, and Person.

Fill in queries.sql with your aiosql queries. While there are multiple ways to do this, I used the following 4 queries: get_title, get_cast, get_person, and get_work. The former 2 accept a title_id as a parameter, and the latter 2 accept a person_id as a parameter.

The following are screenshots from calling the following endpoints.

Call to /titles/tt2194499
Figure 1. Call to /titles/tt2194499
Call to /cast/tt2194499
Figure 2. Call to /cast/tt2194499
Call to /people/nm1046097
Figure 3. Call to /people/nm1046097

Please replicate each of these screenshots with your own screenshot for the following different endpoints.

  • GET /titles/tt1754656

  • GET /cast/tt1754656

  • GET /people/nm0748620

Don’t forget you can run the following to load up our environment.

module use /anvil/projects/tdm/opt/core
module load tdm
module load python/f2022-s2023

In addition, you can run the following to find an unused port.

find_port # for example, 7777

Then, to run your backend from your $SCRATCH/imdb directory, you can run the following.

python3 -m uvicorn backend.api.api:app --reload --port 7777

You can nest pydantic models. For example, in my Person model, I have a list[Work] field. This is a list of Work objects.

Items to submit
  • The entire directory, with all files and folders in the imdb directory.

  • A jupyter notebook containing the screenshots demonstrating the working endpoints.

Please make sure to double check that your submission is complete, and contains all of your code and output before submitting. If you are on a spotty internet connection, it is recommended to download your submission after submitting it to make sure what you think you submitted, was what you actually submitted.

In addition, please review our submission guidelines before submitting your project.