๐ Why Python for Backend?
- Easy to Learn: Clean, readable syntax
- Fast Development: Less code, more productivity
- Rich Ecosystem: Thousands of packages
- Great Frameworks: Django, FastAPI, Flask
- Data Science Integration: ML/AI capabilities
- Strong Community: Excellent documentation
โก FastAPI - Modern & Fast
Getting Started
# Install
pip install fastapi uvicorn[standard]
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
# Run
uvicorn main:app --reload
# Visit: http://localhost:8000
# Docs: http://localhost:8000/docsRequest Body with Pydantic
from pydantic import BaseModel, EmailStr
from typing import Optional
class User(BaseModel):
name: str
email: EmailStr
age: int
is_active: Optional[bool] = True
@app.post("/users/")
def create_user(user: User):
return {
"message": "User created",
"user": user
}
# Automatic validation!
# POST /users/
# {
# "name": "John",
# "email": "john@example.com",
# "age": 30
# }Database with SQLAlchemy
# Install
pip install sqlalchemy psycopg2-binary
# database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "postgresql://user:password@localhost/dbname"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# models.py
from sqlalchemy import Column, Integer, String
from database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String)
email = Column(String, unique=True, index=True)
# main.py
from fastapi import Depends
from sqlalchemy.orm import Session
from database import SessionLocal, engine
import models
models.Base.metadata.create_all(bind=engine)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/users/")
def create_user(user: UserCreate, db: Session = Depends(get_db)):
db_user = models.User(name=user.name, email=user.email)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_userAuthentication with JWT
# Install
pip install python-jose[cryptography] passlib[bcrypt]
# auth.py
from passlib.context import CryptContext
from jose import JWTError, jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password):
return pwd_context.hash(password)
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# main.py
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.post("/token")
def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(form_data.username, form_data.password)
if not user:
raise HTTPException(status_code=401, detail="Invalid credentials")
access_token = create_access_token(data={"sub": user.email})
return {"access_token": access_token, "token_type": "bearer"}
@app.get("/users/me")
def read_users_me(token: str = Depends(oauth2_scheme)):
# Verify token and return user
return current_user๐ธ Django - Batteries Included
Getting Started
# Install
pip install django djangorestframework
# Create project
django-admin startproject myproject
cd myproject
python manage.py startapp api
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'rest_framework',
'api',
]
# models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
# Migrate
python manage.py makemigrations
python manage.py migrate
# Run server
python manage.py runserverDjango REST Framework
# serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'name', 'email', 'created_at']
# views.py
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# urls.py
from rest_framework.routers import DefaultRouter
from .views import UserViewSet
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = router.urls
# Automatic endpoints:
# GET /users/ - List all users
# POST /users/ - Create user
# GET /users/{id}/ - Get user
# PUT /users/{id}/ - Update user
# DELETE /users/{id}/ - Delete user๐ Security Best Practices
- Environment Variables: Use python-dotenv for secrets
- Password Hashing: bcrypt or argon2
- SQL Injection: Use ORM, parameterized queries
- CORS: Configure allowed origins
- Rate Limiting: Prevent abuse
- Input Validation: Pydantic models
- HTTPS Only: Enforce in production
๐ฆ Project Structure
# FastAPI Project myproject/ โโโ app/ โ โโโ __init__.py โ โโโ main.py โ โโโ models.py โ โโโ schemas.py โ โโโ database.py โ โโโ auth.py โ โโโ routers/ โ โโโ __init__.py โ โโโ users.py โ โโโ posts.py โโโ tests/ โ โโโ test_users.py โ โโโ test_posts.py โโโ .env โโโ requirements.txt โโโ README.md # Django Project myproject/ โโโ myproject/ โ โโโ settings.py โ โโโ urls.py โ โโโ wsgi.py โโโ api/ โ โโโ models.py โ โโโ views.py โ โโโ serializers.py โ โโโ urls.py โโโ manage.py โโโ requirements.txt
๐ Deployment
Docker
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:๐งช Testing
# Install
pip install pytest pytest-asyncio httpx
# test_main.py
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Hello World"}
def test_create_user():
response = client.post(
"/users/",
json={"name": "John", "email": "john@example.com", "age": 30}
)
assert response.status_code == 200
assert response.json()["name"] == "John"
# Run tests
pytest๐ Development Checklist
- โ Virtual environment setup
- โ Database configured
- โ Models and schemas defined
- โ Authentication implemented
- โ Input validation
- โ Error handling
- โ CORS configured
- โ Rate limiting
- โ Tests written
- โ API documentation
- โ Environment variables
- โ Docker setup
๐ฏ Conclusion
Python is excellent for backend development. FastAPI is perfect for modern APIs with automatic documentation and type safety. Django is great for full-featured applications with admin panel and ORM. Choose based on your project needs and start building!
๐ง API Testing Tools
Test your Python APIs with our JSON formatter and validation tools.
JSON Formatter โ