Building a Movie Database with FastAPI: A Step-by-Step Guide

Why FastAPI?

FastAPI is a modern, high-performance web framework for building APIs. With its server-side rendering features and type hints for Python ≥ v3.6.0, it’s an ideal choice for building robust and efficient applications. Plus, it supports both client-side and server-side development.

Key Features of FastAPI

  • Comparable speed to Node.js and Go
  • Reduced possibility of human-caused errors
  • Excellent support for code editors
  • Eliminates code duplication
  • Standards-based

Getting Started with FastAPI

To build a movie database application with FastAPI, we’ll need to set up our project structure. Create a new directory called server-side-rendering-with-fastapi and navigate to it. Then, create the following subdirectories:

  • static for static files
  • templates for HTML pages
  • database.py for database connections
  • model.py for database models
  • schema.py for database schema

Setting Up the Virtual Environment

Create a virtual environment using virtualenv to isolate our Python project. Run the following commands:


python -m virtualenv venv
source venv/bin/activate

Installing Dependencies

Install the necessary packages for our project:


pip install fastapi uvicorn jinja2 python-multipart sqlalchemy mysql-connector-python

Creating the FastAPI Server

Create a main.py file in the project’s root directory and add the following code:


from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.requests import Request
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Welcome to this fantastic app!"}

Setting Up SQLAlchemy

Install SQLAlchemy and MySQL Connector/Python:


pip install sqlalchemy mysql-connector-python

Create a database.py file and add the following code:


from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine("mysql://user:password@localhost/dbname")
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

Creating a Database Model

Create a model.py file and add the following code:


from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Movie(Base):
    __tablename__ = "movies"
    id = Column(Integer, primary_key=True)
    name = Column(String(50), unique=True)
    description = Column(String(200))

Creating a Database Schema

Create a schema.py file and add the following code:


from pydantic import BaseModel
from sqlalchemy import Column, Integer, String

class MovieSchema(BaseModel):
    name: str
    description: str

Rendering Templates

Create a templates directory and add an index.html file:


<!DOCTYPE html>
<html>
  <head>
    <title>Movies</title>
  </head>
  <body>
    <h1>Movies</h1>
    <ul>
      {% for movie in movies %}
        <li>{{ movie.name }} - {{ movie.description }}</li>
      {% endfor %}
    </ul>
  </body>
</html>

Creating a Movie Form

Add the following code to index.html:


<form>
  <label>Name:</label>
  <input type="text" name="name"><br><br>
  <label>Description:</label>
  <textarea name="description"></textarea><br><br>
  <input type="submit" value="Submit">
</form>

Updating Movies

Create a patch route to update movies:


@app.patch("/movies/{id}")
async def update_movie(id: int, movie: MovieSchema):
    db_movie = db.query(Movie).filter(Movie.id == id).first()
    if db_movie:
        db_movie.name = movie.name
        db_movie.description = movie.description
        db.commit()
        return JSONResponse(status_code=200, content={"message": "Movie updated successfully"})
    return JSONResponse(status_code=404, content={"message": "Movie not found"})

Deleting Movies

Create a delete route to delete movies:


@app.delete("/movies/{id}")
async def delete_movie(id: int):
    db_movie = db.query(Movie).filter(Movie.id == id).first()
    if db_movie:
        db.delete(db_movie)
        db.commit()
        return JSONResponse(status_code=200, content={"message": "Movie deleted successfully"})
    return JSONResponse(status_code=404, content={"message": "Movie not found"})

Leave a Reply