Skip to content

Commit 57a8f52

Browse files
authored
Initial Python Backend Scaffolding: database setup, models, error handling and two endpoints (#4)
* feat(backend): init FastAPI Movies API with utils, error handling and onboarding docs - Set up FastAPI backend for Movies API - Implement create_success_response and create_error_response utils - Add MongoDB error mapper and global exception handler - Add .gitignore for Python, FastAPI, MongoDB data - Write detailed onboarding Readme with setup, FastAPI leaning and project mapping - Verified parity with TS response formatting and error handling * chore: Restructured project and added initial unit test setup * feat(api): add create_models_batch endpoint and added createMovieRequest model * chore: removing incomplete unit tests * fix(pr feedback & dirty response data): The current mflix db has years with special chars within them. This fix strips all non-digit chars from the year field or sets the year field to none of the string is empty. Typos, spacing, and renaming addressed as well. Removed error msg handling explanation. * chore: Adopting pip-tools pinning strategy
1 parent 0dac316 commit 57a8f52

9 files changed

Lines changed: 824 additions & 0 deletions

File tree

server/python/.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#-------------------------
2+
# Python / FastAPI backend
3+
#-------------------------
4+
5+
# Byte-compiled / optimized files
6+
__pycache__/
7+
*.py[cod]
8+
*$py.class
9+
10+
# Virtual environment
11+
.venv/
12+
13+
# Environment variables
14+
.env
15+
16+
#MacOS files
17+
.DS_Store

server/python/README.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Welcome to the Python Backend
2+
3+
TOC
4+
1. [Overview](#overview)
5+
2. [Getting Setup](#getting-setup)
6+
3. [Learning FastAPI](#learning-fastapi)
7+
4. [Exploring the Codebase](#exploring-the-codebase)
8+
5. [Feature Parity Status](#feature-parity-status)
9+
6. [Utilities and Nice to Know](#nice-to-know)
10+
11+
12+
## Overview
13+
We're porting our Express backend to Python/FastAPI to achieve **functional parity** - same endpoints, same responses, same MongoDB operations. This allows one frontend to work with multiple backends.
14+
15+
16+
**Important**: We're not rewriting - we're replicating behavior exactly. So this means we are figuring out the pythonic way of doing things. You will find that we can accomplish things with Fast in fewer lines of code than in Express.
17+
18+
## Getting Setup
19+
0. Install Python if you don't already have it. (*Depending on your version of python, you might need to use python3 and pip3 vs python and pip*)
20+
1. Clone from my fork of the main repo.
21+
```sh
22+
https://github.com/tmcneil-mdb/docs-sample-apps.git
23+
```
24+
25+
2. Checkout my branch
26+
```sh
27+
git checkout python-backend-setup
28+
```
29+
30+
4. Verify you are on the right branch
31+
```sh
32+
git branch
33+
```
34+
5. In the root directory. /python, make a virtual environment.
35+
```sh
36+
python -m venv .venv
37+
```
38+
6. Activate the virtual environment
39+
```sh
40+
source .venv/bin/activate
41+
```
42+
7. Navigate back to /python, install the required packages.
43+
```sh
44+
pip install -r requirements.txt
45+
```
46+
8. Create an .env file at the /python root.
47+
It should have this format:
48+
```python
49+
MONGO_URI="place your connection string here"
50+
MONGO_DB="sample_mflix"
51+
```
52+
9. Navigate back to the root and start the server.
53+
```sh
54+
fastapi dev main.py or uvicorn main:app --reload
55+
```
56+
(NOTE: THESE WONT WORK IF THE VIRTUAL ENVIRONMENT IS NOT ACTIVATED)
57+
10. Click the link in the terminal or visit ```localhost:8000/docs```
58+
11. Try visiting ```localhost:8000/api/movies```.
59+
60+
If the setup ran correctly, you should see data 🎉
61+
62+
*I recommend having your atlas instance up to explore your data and query the db directly.*
63+
64+
**Troubleshooting**: If commands fail, ensure your virtual environment is activated (you should see `(.venv)` in your terminal prompt).
65+
66+
67+
## Learning FastAPI
68+
Before diving into the repo, I suggest spending some time with the official [FastAPI tutorial](https://fastapi.tiangolo.com/tutorial/).
69+
70+
You only need to read up to the 'Request Body' section to get comfortable. *The query parameters and path parameters section can be read later.*
71+
72+
Key Takeaways:
73+
- Decorators (@app.get, @app.post,etc.)
74+
- Query, path, and body parameters
75+
- Pydantic validation/ serialization
76+
- Automatic JSON responses
77+
- Built-in docs and testing at '/docs'
78+
79+
80+
## Exploring the Codebase
81+
Once you have completed the tutorial, I would suggest exploring the code and just noticing the differences between Express and Python. The apps are setup similarly but there are some small differences.
82+
83+
### Architecture
84+
|Layer|Purpose|Express Equivalent| Differences|
85+
|:---|:-------|:----------|:------|
86+
|Routes <br> `src/routers/movies.py`| Defines all /movies endpoints (GET, POST, PUT, etc.)| /controllers/movieController.ts |The movies.ts file inside the routes file in the Express backend it actually wiring up the endpoints. Fast handles this for us in the main.py in one line. ```app.include_router(movies.router, prefix="/api/movies", tags=["movies"])```|
87+
|Models <br> `src/models/models.py`| Pydantic schema for validating and serializing request/response data.| /types/index.ts|There are some differences in how the models are constructed. Take note on how nested classes are handled.|
88+
|Utils <br> `src/utils/errorHandler.py`| Centralized utilities for responses, error handling and MongoDB exception mapping.|utils/errorHandler.ts |Express requires devs to write exception handling and validation on their own. Pydanic handles the validation and exception handling is a bit cleaner in Fast. You will notice the most differences here.|
89+
|Database <br>`src/database/mongo_client.py`| Handles the connection to the db|/config/database.ts| *The current database file does not have feature parity with the Express version*|
90+
91+
92+
## Feature Parity Status
93+
|Feature|Status|Owner|Notes|
94+
|:------|:-----|:----|:----|
95+
|Global Exception Handling| DONE| - |Found in Utils |
96+
|JSON Response Matching| DONE | - |Found in Utils|
97+
|CRUD- ```insertOne()```| Not Started| Angela| - |
98+
|CRUD- ```insertMany()```| Not Started| Taylor| - |
99+
|CRUD- ```findOne()```| Not Started| Angela| - |
100+
|CRUD- ```find()```| DONE| - | Found in movies.py as ```get_all_movies()``` This is a good function to look at to understand query parameters, requests and responses. Your functions will be simpler than this. But that is a good base to start with.|
101+
|CRUD- ```updateOne()```| Not Started| Angela| - |
102+
|CRUD- ```updateMany()```| Not Started| Taylor| - |
103+
|CRUD- ```deleteOne()```| Not Started| Angela| - |
104+
|CRUD- ```deleteMany()```| Not Started| Taylor| -|
105+
|CRUD- ```findOne()```| Not Started| Angela| - |
106+
|CRUD- ```findOneAndDelete()```| Not Started| Angela| This one is a bit harder but I figure this could be a fun challenge.|
107+
108+
109+
## Nice to Know
110+
### Utilities (errorHandler.py)
111+
This module provides a parity replacement for the Express errorHandler.ts file. It provides the same response shapes and error handling and removes the middleware.
112+
113+
- create_success_response(data,message) - creates a success response with the same shape as the Express version.
114+
- create_error_response(message,code,details) - creates a error response with the same shape as the Express version.
115+
- parse_mongo_exception(exc) - ensures PyMongo exceptions return JSON identical to the Express Version
116+
- register_error_handlers - hooks our error system into the Fast app
117+
118+
Fast automatically handles async and validation errors, so there is no need for asyncHandler or validateRequiredFields from the TS version.
119+
120+
### Useful Links
121+
- [Main Repo]( https://github.com/mongodb/docs-sample-apps/tree/main )
122+
- [Sample App Scoping Doc](https://docs.google.com/document/d/12dROckw_Cp0ku2IIGku-ch7MvEuBPo0V4Gs-5wQgeHQ/edit?tab=t.0)
123+
- [Sample App Project Description & Breakdown Doc](https://docs.google.com/document/d/1xv2dmcNrT-HYk5TBE-KtVDPmW0274rpBZ0_0QmC66ac/edit?tab=t.0#heading=h.ki9tatw08ilc)

server/python/main.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from fastapi import FastAPI
2+
from src.routers import movies
3+
from src.utils.errorHandler import register_error_handlers
4+
5+
app = FastAPI()
6+
register_error_handlers(app)
7+
app.include_router(movies.router, prefix="/api/movies", tags=["movies"])
8+
9+
10+
11+
12+
13+
14+
15+
16+
#------------------------------------
17+
# Testing error endpoints. Will be removed later
18+
#------------------------------------
19+
20+
'''
21+
@app.get("/")
22+
async def root():
23+
return {"message": "Backend is running!"}
24+
25+
@app.get("/test-duplicate")
26+
async def test_duplicate():
27+
from pymongo.errors import DuplicateKeyError
28+
raise DuplicateKeyError("This is a test duplicate key error.")
29+
30+
@app.get("/test-generic")
31+
async def test_generic():
32+
from pymongo.errors import PyMongoError
33+
raise PyMongoError("This is a test generic pymongo error.")
34+
'''

server/python/requirements.in

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# ==============================================================================
2+
# 1. CORE WEB FRAMEWORK & ASGI SERVER
3+
# FastAPI and its main components.
4+
# ------------------------------------------------------------------------------
5+
fastapi~=0.120.0 # The main web framework
6+
starlette~=0.48.0 # FastAPI's underlying ASGI toolkit
7+
uvicorn~=0.38.0 # Production-ready ASGI server
8+
uvloop~=0.22.0 # Optional: High-performance event loop for uvicorn
9+
websockets~=15.0.0 # For WebSocket support
10+
watchfiles~=1.1.0 # For hot-reloading in development
11+
12+
# ==============================================================================
13+
# 2. DATA VALIDATION & CORE UTILITIES
14+
# Primary libraries for data models and environment config.
15+
# ------------------------------------------------------------------------------
16+
pydantic~=2.12.0 # Data validation and settings management
17+
python-dotenv~=1.1.0 # For loading configuration from .env files
18+
python-multipart~=0.0.0 # For parsing form data and file uploads
19+
PyYAML~=6.0.0 # For handling YAML configuration or data
20+
21+
# ==============================================================================
22+
# 3. DATABASE & CONNECTIVITY
23+
# Database driver and necessary utilities.
24+
# ------------------------------------------------------------------------------
25+
pymongo~=4.15.0 # MongoDB driver
26+
dnspython~=2.8.0 # Required for SRV record lookups by pymongo (e.g., MongoDB Atlas)
27+
28+
# ==============================================================================
29+
# 4. HTTP CLIENT & UTILITIES
30+
# Primary libraries for making external HTTP requests.
31+
# ------------------------------------------------------------------------------
32+
httpx~=0.28.0 # Asynchronous HTTP client for requests to external APIs
33+
email-validator~=2.3.0 # Utility for validating email addresses
34+
35+
# ==============================================================================
36+
# 5. CLI & DEVELOPMENT TOOLS
37+
# Tools for building command-line interfaces for management tasks.
38+
# ------------------------------------------------------------------------------
39+
typer~=0.20.0 # Library for creating command-line applications
40+
fastapi-cli~=0.0.0 # Tools to run and manage FastAPI projects
41+
fastapi-cloud-cli~=0.3.0 # Tools for cloud deployment (specific to your pipeline)
42+
43+
# ==============================================================================
44+
# 6. TESTING & MONITORING
45+
# Frameworks for ensuring code quality and production health.
46+
# ------------------------------------------------------------------------------
47+
pytest~=8.4.0 # Primary testing framework
48+
pytest-asyncio~=1.2.0 # Plugin to make asynchronous tests easy with pytest
49+
sentry-sdk~=2.42.0 # For error tracking and performance monitoring
50+
51+
# ==============================================================================
52+
# 7. LOGGING AND TERMINAL OUTPUT
53+
# Libraries for rich console output and debugging.
54+
# ------------------------------------------------------------------------------
55+
rich~=14.2.0 # For rich, formatted terminal output
56+
rich-toolkit~=0.15.0 # Extensions for the 'rich' library

server/python/requirements.txt

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#
2+
# This file is autogenerated by pip-compile with Python 3.13
3+
# by the following command:
4+
#
5+
# pip-compile requirements.in
6+
#
7+
annotated-doc==0.0.3
8+
# via fastapi
9+
annotated-types==0.7.0
10+
# via pydantic
11+
anyio==4.11.0
12+
# via
13+
# httpx
14+
# starlette
15+
# watchfiles
16+
certifi==2025.10.5
17+
# via
18+
# httpcore
19+
# httpx
20+
# sentry-sdk
21+
click==8.3.0
22+
# via
23+
# rich-toolkit
24+
# typer
25+
# uvicorn
26+
dnspython==2.8.0
27+
# via
28+
# -r requirements.in
29+
# email-validator
30+
# pymongo
31+
email-validator==2.3.0
32+
# via
33+
# -r requirements.in
34+
# pydantic
35+
fastapi==0.120.0
36+
# via -r requirements.in
37+
fastapi-cli==0.0.14
38+
# via -r requirements.in
39+
fastapi-cloud-cli==0.3.1
40+
# via -r requirements.in
41+
h11==0.16.0
42+
# via
43+
# httpcore
44+
# uvicorn
45+
httpcore==1.0.9
46+
# via httpx
47+
httptools==0.7.1
48+
# via uvicorn
49+
httpx==0.28.1
50+
# via
51+
# -r requirements.in
52+
# fastapi-cloud-cli
53+
idna==3.11
54+
# via
55+
# anyio
56+
# email-validator
57+
# httpx
58+
iniconfig==2.3.0
59+
# via pytest
60+
markdown-it-py==4.0.0
61+
# via rich
62+
mdurl==0.1.2
63+
# via markdown-it-py
64+
packaging==25.0
65+
# via pytest
66+
pluggy==1.6.0
67+
# via pytest
68+
pydantic[email]==2.12.3
69+
# via
70+
# -r requirements.in
71+
# fastapi
72+
# fastapi-cloud-cli
73+
pydantic-core==2.41.4
74+
# via pydantic
75+
pygments==2.19.2
76+
# via
77+
# pytest
78+
# rich
79+
pymongo==4.15.3
80+
# via -r requirements.in
81+
pytest==8.4.2
82+
# via
83+
# -r requirements.in
84+
# pytest-asyncio
85+
pytest-asyncio==1.2.0
86+
# via -r requirements.in
87+
python-dotenv==1.1.1
88+
# via
89+
# -r requirements.in
90+
# uvicorn
91+
python-multipart==0.0.20
92+
# via -r requirements.in
93+
pyyaml==6.0.3
94+
# via
95+
# -r requirements.in
96+
# uvicorn
97+
rich==14.2.0
98+
# via
99+
# -r requirements.in
100+
# rich-toolkit
101+
# typer
102+
rich-toolkit==0.15.1
103+
# via
104+
# -r requirements.in
105+
# fastapi-cli
106+
# fastapi-cloud-cli
107+
rignore==0.7.1
108+
# via fastapi-cloud-cli
109+
sentry-sdk==2.42.1
110+
# via
111+
# -r requirements.in
112+
# fastapi-cloud-cli
113+
shellingham==1.5.4
114+
# via typer
115+
sniffio==1.3.1
116+
# via anyio
117+
starlette==0.48.0
118+
# via
119+
# -r requirements.in
120+
# fastapi
121+
typer==0.20.0
122+
# via
123+
# -r requirements.in
124+
# fastapi-cli
125+
# fastapi-cloud-cli
126+
typing-extensions==4.15.0
127+
# via
128+
# fastapi
129+
# pydantic
130+
# pydantic-core
131+
# rich-toolkit
132+
# typer
133+
# typing-inspection
134+
typing-inspection==0.4.2
135+
# via pydantic
136+
urllib3==2.5.0
137+
# via sentry-sdk
138+
uvicorn[standard]==0.38.0
139+
# via
140+
# -r requirements.in
141+
# fastapi-cli
142+
# fastapi-cloud-cli
143+
uvloop==0.22.1
144+
# via
145+
# -r requirements.in
146+
# uvicorn
147+
watchfiles==1.1.1
148+
# via
149+
# -r requirements.in
150+
# uvicorn
151+
websockets==15.0.1
152+
# via
153+
# -r requirements.in
154+
# uvicorn

0 commit comments

Comments
 (0)