Skip to content

Commit 5dd42bc

Browse files
authored
Boilerplate (#1)
1 parent 7237a10 commit 5dd42bc

13 files changed

Lines changed: 1023 additions & 3 deletions

File tree

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ ipython_config.py
8585
# pyenv
8686
# For a library or package, you might want to ignore these files since the code is
8787
# intended to run in multiple environments; otherwise, check them in:
88-
# .python-version
88+
.python-version
8989

9090
# pipenv
9191
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
@@ -173,7 +173,7 @@ cython_debug/
173173
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174174
# and can be added to the global gitignore or merged into this file. For a more nuclear
175175
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
176-
#.idea/
176+
.idea/
177177

178178
# Abstra
179179
# Abstra is an AI-powered process automation framework.

README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,31 @@
1-
# python-fastapi-template
1+
# python-fastapi-template
2+
3+
A simple and idiomatic REST API boilerplate in Python using [FastAPI](https://fastapi.tiangolo.com/), designed for clarity, modularity and extensibility.
4+
Built to showcase best practices in Python backend development and serve as a solid foundation for future projects.
5+
6+
## ✨ Features
7+
8+
- 🧱 Modular project structure (`api/`, `models/`, `services/`, etc.)
9+
- 🔀 Routing with versioned endpoints
10+
- 📄 OpenAPI docs auto-generated (`/docs`, `/redoc`)
11+
- ✅ Data validation and typing with Pydantic v2
12+
- 🧪 Async-ready test setup with `pytest`, `httpx`, `pytest-asyncio` (in progress)
13+
- 🐳 Minimal Docker support (in progress)
14+
- 🧰 Designed as a reusable starter template
15+
16+
## 📦 Technologies
17+
18+
- Python 3.11+
19+
- FastAPI
20+
- Uvicorn (ASGI server)
21+
- Pydantic v2
22+
23+
## 🚀 Getting Started
24+
25+
```bash
26+
# Install dependencies
27+
poetry install
28+
29+
# Run the development server
30+
poetry run uvicorn app.main:app --reload
31+
```

app/__init__.py

Whitespace-only changes.

app/api/__init__.py

Whitespace-only changes.

app/api/users.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from fastapi import APIRouter, HTTPException
2+
from app.models.user import User, UserCreate
3+
from app.services.user_service import save_user, get_all_users
4+
5+
router = APIRouter()
6+
7+
8+
@router.post("/", response_model=User)
9+
async def create_user(user: UserCreate):
10+
return await save_user(user)
11+
12+
13+
@router.get("/", response_model=list[User])
14+
async def get_users():
15+
return await get_all_users()

app/main.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import logging
2+
import sys
3+
4+
from fastapi import FastAPI
5+
from app.api import users
6+
7+
log_format = '%(asctime)s | %(levelname)-8s | %(name)-12s - %(message)s'
8+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format=log_format)
9+
10+
app = FastAPI(title="Python FastAPI Template", version="0.1.0")
11+
12+
app.include_router(users.router, prefix="/api/v1/users", tags=["User"])

app/models/__init__.py

Whitespace-only changes.

app/models/user.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from pydantic import BaseModel, EmailStr
2+
3+
4+
class UserBase(BaseModel):
5+
email: EmailStr
6+
7+
8+
class UserCreate(UserBase):
9+
name: str
10+
11+
12+
class User(UserBase):
13+
id: int
14+
name: str

app/services/__init__.py

Whitespace-only changes.

app/services/user_service.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from app.models.user import User, UserCreate
2+
3+
_fake_db: list[User] = []
4+
5+
6+
async def save_user(user: UserCreate) -> User:
7+
user_id = len(_fake_db) + 1
8+
new_user = User(id=user_id, **user.model_dump())
9+
_fake_db.append(new_user)
10+
return new_user
11+
12+
13+
async def get_all_users() -> list[User]:
14+
return _fake_db

0 commit comments

Comments
 (0)