Tentu! Berikut adalah contoh lengkap untuk setiap file dan folder dalam struktur folder FastAPI yang telah saya jelaskan sebelumnya. Saya akan memberikan contoh kode untuk setiap file utama, termasuk contoh main.py, API endpoints, model, schema, dan sebagainya. Ini akan memberikan gambaran lebih jelas tentang bagaimana mengorganisasi aplikasi FastAPI yang skalabel.

1. my_fastapi_project/app/main.py#

from fastapi import FastAPI
from app.api.v1 import endpoints

app = FastAPI()

# Include the routes from the API version 1
app.include_router(endpoints.router, prefix="/v1", tags=["v1"])

2. my_fastapi_project/app/api/v1/endpoints/user.py#

from fastapi import APIRouter, Depends
from app.schemas.user import User, UserCreate
from app.services.user_service import create_user, get_user

router = APIRouter()

@router.post("/users/", response_model=User)
def create_user_endpoint(user: UserCreate):
    return create_user(user)

@router.get("/users/{user_id}", response_model=User)
def get_user_endpoint(user_id: int):
    return get_user(user_id)

3. my_fastapi_project/app/api/v1/endpoints/item.py#

from fastapi import APIRouter, Depends
from app.schemas.item import Item, ItemCreate
from app.services.item_service import create_item, get_item

router = APIRouter()

@router.post("/items/", response_model=Item)
def create_item_endpoint(item: ItemCreate):
    return create_item(item)

@router.get("/items/{item_id}", response_model=Item)
def get_item_endpoint(item_id: int):
    return get_item(item_id)

4. my_fastapi_project/app/core/config.py#

import os
from dotenv import load_dotenv

load_dotenv()  # Load environment variables from .env

class Config:
    API_KEY = os.getenv("API_KEY")
    DB_URL = os.getenv("DATABASE_URL")
    SECRET_KEY = os.getenv("SECRET_KEY")

config = Config()

5. my_fastapi_project/app/core/security.py#

from passlib.context import CryptContext

# Password hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def hash_password(password: str) -> str:
    return pwd_context.hash(password)

def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)

6. my_fastapi_project/app/models/user.py#

from sqlalchemy import Column, Integer, String
from app.db.session import Base

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    username = Column(String, unique=True, index=True)
    hashed_password = Column(String)

7. my_fastapi_project/app/models/item.py#

from sqlalchemy import Column, Integer, String
from app.db.session import Base

class Item(Base):
    __tablename__ = "items"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    description = Column(String)

8. my_fastapi_project/app/schemas/user.py#

from pydantic import BaseModel

class User(BaseModel):
    id: int
    username: str

    class Config:
        orm_mode = True

class UserCreate(BaseModel):
    username: str
    password: str

9. my_fastapi_project/app/schemas/item.py#

from pydantic import BaseModel

class Item(BaseModel):
    id: int
    name: str
    description: str

    class Config:
        orm_mode = True

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

10. my_fastapi_project/app/services/user_service.py#

from app.models.user import User
from app.schemas.user import UserCreate
from app.db.session import SessionLocal
from app.core.security import hash_password

def create_user(user_create: UserCreate):
    db = SessionLocal()
    hashed_password = hash_password(user_create.password)
    db_user = User(username=user_create.username, hashed_password=hashed_password)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    db.close()
    return db_user

def get_user(user_id: int):
    db = SessionLocal()
    db_user = db.query(User).filter(User.id == user_id).first()
    db.close()
    return db_user

11. my_fastapi_project/app/services/item_service.py#

from app.models.item import Item
from app.schemas.item import ItemCreate
from app.db.session import SessionLocal

def create_item(item_create: ItemCreate):
    db = SessionLocal()
    db_item = Item(name=item_create.name, description=item_create.description)
    db.add(db_item)
    db.commit()
    db.refresh(db_item)
    db.close()
    return db_item

def get_item(item_id: int):
    db = SessionLocal()
    db_item = db.query(Item).filter(Item.id == item_id).first()
    db.close()
    return db_item

12. my_fastapi_project/app/db/session.py#

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

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"  # Replace with your actual database URL

engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

# To initialize the database (create tables)
def init_db():
    Base.metadata.create_all(bind=engine)

13. my_fastapi_project/app/tests/test_user.py#

from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_create_user():
    response = client.post("/v1/users/", json={"username": "testuser", "password": "password123"})
    assert response.status_code == 200
    assert response.json()["username"] == "testuser"

def test_get_user():
    response = client.post("/v1/users/", json={"username": "testuser", "password": "password123"})
    user_id = response.json()["id"]
    
    response = client.get(f"/v1/users/{user_id}")
    assert response.status_code == 200
    assert response.json()["id"] == user_id

14. my_fastapi_project/app/utils/date_utils.py#

from datetime import datetime

def current_time():
    return datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")

15. my_fastapi_project/.env#

API_KEY=your_api_key_here
DATABASE_URL=sqlite:///./test.db  # Replace with your actual database URL
SECRET_KEY=your_secret_key_here

16. my_fastapi_project/requirements.txt#

fastapi
uvicorn
sqlalchemy
pydantic
passlib
python-dotenv

17. my_fastapi_project/Dockerfile (optional)#

# Use official Python image
FROM python:3.10-slim

# Set working directory
WORKDIR /app

# Copy requirements and install
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application
COPY . .

# Expose port 8000 for FastAPI
EXPOSE 8000

# Run the application with Uvicorn
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

18. my_fastapi_project/docker-compose.yml (optional)#

version: "3.8"
services:
  app:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=sqlite:///./test.db
    volumes:
      - .:/app
    command: uvicorn app.main:app --host 0.0.0.0 --port 8000

Conclusion#

Dengan struktur ini, Anda memiliki aplikasi FastAPI yang terorganisir dengan baik, memisahkan setiap bagian dari aplikasi (API, model, schema, logika bisnis, dll). Ini memudahkan pengembangan dan pemeliharaan proyek, serta mendukung pengembangan lebih lanjut saat aplikasi Anda tumbuh.