Welcome to the Movie Theater API project! This is an educational assignment designed to help you practice and improve your skills in building web applications using FastAPI, SQLAlchemy, and Docker. The foundation of the project has already been prepared, including:
- Database setup: A SQLite database is configured and ready to use.
- Data population: The database can be filled with data from a pre-existing dataset using a pre-written script.
- Docker integration: The project is pre-configured to run in Docker, simplifying the setup process.
- Project structure: The core project structure, including routing, database models, and utility scripts, is already in place.
The project is structured to facilitate modular development and ease of maintenance. Below is a detailed explanation of the directories and files:
Here is a visual representation of the project structure:
.
├── Dockerfile
├── README.md
├── commands
│ └── run.sh
├── docker-compose.yml
├── poetry.lock
├── pyproject.toml
├── pytest.ini
└── src
├── config
│ ├── __init__.py
│ └── settings.py
├── database
│ ├── __init__.py
│ ├── models.py
│ ├── populate.py
│ ├── seed_data
│ │ └── imdb_movies.csv
│ ├── session.py
│ └── source
│ └── movies.db
├── main.py
├── routes
│ ├── __init__.py
│ └── movies.py
├── schemas
│ ├── __init__.py
│ └── movies.py
└── tests
├── __init__.py
├── conftest.py
└── test_integration
├── __init__.py
└── test_movies.py
This representation outlines the hierarchy of files and directories within the project, showing the relationships between components.
Dockerfile
: Contains the instructions to build the Docker image for the application.docker-compose.yml
: Defines the services, networks, and volumes for Docker Compose to run the project.poetry.lock
: Dependency lock file managed by Poetry to ensure consistent environments.pyproject.toml
: Configuration file for Poetry, defining project metadata and dependencies.README.md
: Placeholder for the project description and instructions (to be completed).commands/run.sh
: A script used to initialize or run the application in a containerized environment.pytest.ini
: Configuration file for Pytest, specifying settings for running tests.
The main source directory for the application.
-
src/config/
settings.py
: Contains project configurations, including paths for the database and seed data. Implements environment-specific settings for testing and development.
-
src/database/
models.py
: Defines the database models using SQLAlchemy.session.py
: Handles the database connection and session management.populate.py
: Includes logic to populate the database with seed data from a CSV file.seed_data/imdb_movies.csv
: CSV file containing sample movie data for initial database seeding.source/movies.db
: SQLite database file (used in non-testing environments).
-
src/routes/
movies.py
: Defines the FastAPI routes (endpoints) for interacting with the movie database.
-
src/schemas/
movies.py
: Contains Pydantic models for request validation and response serialization.
-
src/tests/
conftest.py
: Defines reusable Pytest fixtures for tests, including database resets and test client setup.test_integration/test_movies.py
: Contains integration tests for the movie-related endpoints to ensure they work as expected.
-
src/main.py
- The entry point of the application. Configures FastAPI and mounts the defined routes.
This structure ensures:
- Clear separation of concerns (e.g., routing, database, configurations, testing).
- Easy integration of Docker for development and production environments.
- Ready-to-use seed data for database initialization during development and testing.
- Modular and maintainable codebase for extending functionality.
The get_db
function is a generator that provides a SQLAlchemy session for interacting with the database. This function is particularly useful in FastAPI as it can be injected into route handlers using the Depends
mechanism. Here’s how you can use it effectively:
from fastapi import Depends, APIRouter
from sqlalchemy.orm import Session
from database import get_db # Import the get_db generator
router = APIRouter()
@router.get("/example")
def example_route(db: Session = Depends(get_db)):
# Use the db session here to interact with the database
- The
Depends
function simplifies injecting dependencies like the database session into your route handlers. - The
get_db
function ensures proper session handling: the session is created before the route logic executes and is closed automatically afterward. - This approach promotes cleaner, more testable code by separating dependency setup from business logic.
You can use this pattern across your application for any routes that need database access.
This project is designed to run with Docker Compose for ease of setup and also supports manual setup for local development.
-
Ensure Docker and Docker Compose are installed on your system.
-
Navigate to the root directory of the project (where the
docker-compose.yml
file is located). -
Run the following command to start the services:
docker-compose up --build
-
When the containers start, the application will:
- Automatically populate the database with movie data from the provided dataset (
imdb_movies.csv
). - Launch the API server, which will be accessible at http://localhost:8000.
- Automatically populate the database with movie data from the provided dataset (
-
To stop the services, press
Ctrl+C
and then run:docker-compose down
If you prefer to run the project without Docker, you can set it up manually by following these steps:
-
Set up a Python virtual environment:
python -m venv .venv
-
Activate the virtual environment:
- On macOS/Linux:
source .venv/bin/activate
- On Windows:
.venv\Scripts\activate
- On macOS/Linux:
-
Install Poetry:
pip install poetry
-
Install project dependencies:
poetry install
-
Populate the database: Run the database seeding script to populate the SQLite database:
python src/database/populate.py
-
Start the FastAPI application:
uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload
The API will be accessible at http://localhost:8000.
- Database Seeding: Whether running through Docker Compose or manually, the database is automatically populated with movie data during the initial setup.
- API Documentation: Once the application is running, you can explore the API documentation at http://localhost:8000/docs.
- Testing: Tests can be executed using
pytest
with the following command:pytest
This setup ensures flexibility, whether you prefer running the project in a containerized environment or directly on your development machine.
In this assignment, you are tasked with continuing the development of the cinema application. Your objective is to implement two endpoints in the schemas/movies.py
and routes/movies.py
files. The rest of the application, including database models and utility functions, has already been provided.
The database/models.py
file contains a MovieModel
class that defines the schema for the movies
table. This table has the following fields:
id
: Primary keyname
: Movie titledate
: Release datescore
: Movie rating (a float between 0 and 100)genre
: Movie genres (comma-separated)overview
: Short description of the moviecrew
: List of cast and creworig_title
: Original title of the moviestatus
: Release status (e.g., "Released", "Post-production")orig_lang
: Original languagebudget
: Movie budgetrevenue
: Revenue generatedcountry
: Country of production
-
Get a Paginated List of Movies
- URL:
/movies/
- Method:
GET
- Query Parameters:
page
(integer, required, default:1
, must be >= 1): The page number to fetch.per_page
(integer, required, default:10
, must be >= 1 and <= 20): Number of movies to fetch per page.
- Responses:
- 200 OK: Returns a paginated list of movies.
- Example Response:
{ "movies": [ { "id": 1, "name": "Creed III", "date": "2023-03-02", "score": 73, "genre": "Drama,Action", "overview": "After dominating the boxing world, Adonis Creed has been thriving in both his career and family life...", "crew": "Michael B. Jordan, Tessa Thompson", "orig_title": "Creed III", "status": "Released", "orig_lang": "English", "budget": 75000000, "revenue": 271616668, "country": "AU" } ], "prev_page": "/theater/movies/?page=1&per_page=10", "next_page": "/theater/movies/?page=3&per_page=10", "total_pages": 1000, "total_items": 9999 }
- Example Response:
- 404 Not Found: If no movies are found.
- Example Response:
{ "detail": "No movies found." }
- Example Response:
- 422 Unprocessable Entity: If
page
orper_page
is invalid.- Example Response:
{ "detail": [ { "loc": ["query", "page"], "msg": "ensure this value is greater than or equal to 1", "type": "value_error.number.not_ge" } ] }
- Example Response:
- 200 OK: Returns a paginated list of movies.
- URL:
-
Get Movie Details by ID
- URL:
/movies/{movie_id}/
- Method:
GET
- Path Parameters:
movie_id
(integer, required): The ID of the movie to fetch.
- Responses:
- 200 OK: Returns detailed information about the movie.
- Example Response:
{ "id": 1, "name": "Creed III", "date": "2023-03-02", "score": 73, "genre": "Drama,Action", "overview": "After dominating the boxing world, Adonis Creed has been thriving in both his career and family life...", "crew": "Michael B. Jordan, Tessa Thompson", "orig_title": "Creed III", "status": "Released", "orig_lang": "English", "budget": 75000000, "revenue": 271616668, "country": "AU" }
- Example Response:
- 404 Not Found: If no movie with the given ID exists.
- Example Response:
{ "detail": "Movie with the given ID was not found." }
- Example Response:
- 200 OK: Returns detailed information about the movie.
- URL:
-
Open the
schemas/movies.py
file and define the following schemas:MovieDetailResponseSchema
: Contains all fields for a single movie, includingid
,name
,date
, etc.MovieListResponseSchema
: Contains a list of movies (movies
), pagination links (prev_page
andnext_page
), and total counts (total_pages
andtotal_items
).
-
Open the
routes/movies.py
file and implement the two endpoints:- Use the provided database session generator (
get_db
) to query the database. - Ensure proper error handling for invalid parameters and missing data.
- Return responses that match the provided examples exactly.
- Use the provided database session generator (
-
Run the provided tests to validate your implementation. Your code must pass all tests for the task to be considered complete.