Table of Contents
- 1. Introduction to Python Web Development
- 2. Environment Setup
- 3. Flask Fundamentals
- 4. FastAPI Basics
- 5. Database and ORM Integration
- 6. Authentication and Security
- 7. RESTful API Development
- 8. Asynchronous Programming
- 9. Testing and Debugging
- 10. Deployment and Best Practices
1. Introduction to Python Web Development
Python offers powerful frameworks for web development, with Flask and FastAPI being among the most popular choices. Flask provides simplicity and flexibility for traditional web applications, while FastAPI excels in building modern, high-performance APIs with automatic documentation generation.
Key advantages of Python web development:
- Rapid prototyping and development speed
- Extensive ecosystem of libraries and packages
- Strong community support and documentation
- Excellent testing frameworks and debugging tools
- Built-in support for async programming
2. Environment Setup
Python Installation and Virtual Environment
# Install Python (using pyenv recommended)
curl https://pyenv.run | bash
pyenv install 3.11.0
pyenv global 3.11.0
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Verify installation
python --version
pip --versionProject Structure
my-python-api/
├── app/
│ ├── __init__.py
│ ├── models/
│ ├── routes/
│ ├── services/
│ └── utils/
├── tests/
├── requirements.txt
├── .env
├── .gitignore
├── main.py
└── README.mdDependencies Installation
# Flask requirements
pip install flask flask-sqlalchemy flask-migrate flask-jwt-extended
pip install flask-cors flask-bcrypt python-dotenv
# FastAPI requirements
pip install fastapi uvicorn sqlalchemy alembic
pip install python-jose[cryptography] passlib[bcrypt]
# Development dependencies
pip install pytest pytest-asyncio black flake8
# Generate requirements.txt
pip freeze > requirements.txt3. Flask Fundamentals
Basic Flask Application
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_jwt_extended import JWTManager
from flask_cors import CORS
import os
db = SQLAlchemy()
migrate = Migrate()
jwt = JWTManager()
def create_app():
app = Flask(__name__)
# Configuration
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-key')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///app.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY', 'jwt-secret')
# Initialize extensions
db.init_app(app)
migrate.init_app(app, db)
jwt.init_app(app)
CORS(app)
# Register blueprints
from app.routes.auth import auth_bp
from app.routes.users import users_bp
from app.routes.posts import posts_bp
app.register_blueprint(auth_bp, url_prefix='/api/auth')
app.register_blueprint(users_bp, url_prefix='/api/users')
app.register_blueprint(posts_bp, url_prefix='/api/posts')
return appFlask Models
# app/models/user.py
from app import db
from flask_bcrypt import generate_password_hash, check_password_hash
from datetime import datetime
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(255), nullable=False)
is_active = db.Column(db.Boolean, default=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
# Relationships
posts = db.relationship('Post', backref='author', lazy=True)
def set_password(self, password):
self.password_hash = generate_password_hash(password).decode('utf-8')
def check_password(self, password):
return check_password_hash(self.password_hash, password)
def to_dict(self):
return {
'id': self.id,
'username': self.username,
'email': self.email,
'is_active': self.is_active,
'created_at': self.created_at.isoformat()
}4. FastAPI Basics
FastAPI Application Setup
# main.py
from fastapi import FastAPI, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.security import HTTPBearer
import uvicorn
import os
app = FastAPI(
title="My Python API",
description="A comprehensive API built with FastAPI",
version="1.0.0"
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Security
security = HTTPBearer()
@app.get("/")
async def root():
return {"message": "Welcome to FastAPI", "version": "1.0.0"}
@app.get("/health")
async def health_check():
return {"status": "healthy", "timestamp": "2024-01-01T00:00:00Z"}
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)Pydantic Models
# app/schemas.py
from pydantic import BaseModel, EmailStr, validator
from typing import Optional, List
from datetime import datetime
class UserBase(BaseModel):
username: str
email: EmailStr
class UserCreate(UserBase):
password: str
@validator('password')
def validate_password(cls, v):
if len(v) < 8:
raise ValueError('Password must be at least 8 characters')
return v
class UserResponse(UserBase):
id: int
is_active: bool
created_at: datetime
class Config:
from_attributes = True
class PostBase(BaseModel):
title: str
content: str
tags: List[str] = []
class PostCreate(PostBase):
pass
class PostResponse(PostBase):
id: int
author_id: int
created_at: datetime
updated_at: Optional[datetime] = None
class Config:
from_attributes = True5. Database and ORM Integration
SQLAlchemy Models
# app/models/database.py
from sqlalchemy import create_engine, Column, Integer, String, Boolean, DateTime, Text, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from datetime import datetime
import os
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./app.db")
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, index=True)
email = Column(String(100), unique=True, index=True)
hashed_password = Column(String(255))
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
posts = relationship("Post", back_populates="author")
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(200), index=True)
content = Column(Text)
author_id = Column(Integer, ForeignKey("users.id"))
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, onupdate=datetime.utcnow)
author = relationship("User", back_populates="posts")
# Create tables
Base.metadata.create_all(bind=engine)Database Connection
# app/database.py
from sqlalchemy.orm import Session
from app.models.database import SessionLocal
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# Database operations
class DatabaseManager:
def __init__(self, db: Session):
self.db = db
def create_user(self, user_data: dict):
user = User(**user_data)
self.db.add(user)
self.db.commit()
self.db.refresh(user)
return user
def get_user_by_email(self, email: str):
return self.db.query(User).filter(User.email == email).first()
def get_posts(self, skip: int = 0, limit: int = 10):
return self.db.query(Post).offset(skip).limit(limit).all()Complete Guide to Python Web Development with Flask & FastAPI
6. Authentication and Security
JWT Authentication
# app/auth.py
from datetime import datetime, timedelta
from jose import JWTError, jwt
from passlib.context import CryptContext
from fastapi import HTTPException, status
import os
SECRET_KEY = os.getenv("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})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
def verify_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise HTTPException(status_code=401, detail="Invalid token")
return username
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
7. RESTful API Development
FastAPI Routes
# app/routes/users.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.database import get_db
from app.schemas import UserCreate, UserResponse
from app.models.database import User
from app.auth import get_password_hash
router = APIRouter()
@router.post("/", response_model=UserResponse)
async def create_user(user: UserCreate, db: Session = Depends(get_db)):
# Check if user exists
existing_user = db.query(User).filter(User.email == user.email).first()
if existing_user:
raise HTTPException(status_code=400, detail="Email already registered")
# Create new user
hashed_password = get_password_hash(user.password)
db_user = User(
username=user.username,
email=user.email,
hashed_password=hashed_password
)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
@router.get("/", response_model=List[UserResponse])
async def get_users(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
users = db.query(User).offset(skip).limit(limit).all()
return users
8. Testing and Debugging
API Testing
# tests/test_users.py
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.main import app
from app.database import get_db
from app.models.database import Base
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
def override_get_db():
try:
db = TestingSessionLocal()
yield db
finally:
db.close()
app.dependency_overrides[get_db] = override_get_db
client = TestClient(app)
def test_create_user():
response = client.post("/api/users/", json={
"username": "testuser",
"email": "[email protected]",
"password": "testpassword123"
})
assert response.status_code == 200
assert response.json()["email"] == "[email protected]"
def test_get_users():
response = client.get("/api/users/")
assert response.status_code == 200
assert isinstance(response.json(), list)
9. Deployment and Best Practices
Production Configuration
Security considerations for production deployment:
- Use environment variables for sensitive data
- Implement proper CORS policies
- Add request rate limiting
- Use HTTPS in production
- Implement proper logging
- Use database connection pooling
# config.py
import os
from functools import lru_cache
class Settings:
app_name: str = "My Python API"
secret_key: str = os.getenv("SECRET_KEY", "fallback-secret-key")
database_url: str = os.getenv("DATABASE_URL", "sqlite:///./app.db")
debug: bool = os.getenv("DEBUG", "False").lower() == "true"
@lru_cache()
def get_settings():
return Settings()
# Docker deployment
# 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", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Performance Optimization
Key optimization strategies:
- Use async/await for I/O operations
- Implement database query optimization
- Add caching layers (Redis)
- Use connection pooling
- Implement background tasks
# Performance example
from fastapi import BackgroundTasks
import asyncio
@router.post("/send-email/")
async def send_email_endpoint(
email: str,
background_tasks: BackgroundTasks
):
background_tasks.add_task(send_email_async, email)
return {"message": "Email will be sent in background"}
async def send_email_async(email: str):
# Simulate async email sending
await asyncio.sleep(5)
print(f"Email sent to {email}")
This guide provides a comprehensive foundation for Python web development using both Flask and FastAPI, covering essential topics from setup to deployment with practical examples and best practices.
