Python Frameworks β€” Django & Flask

Routing, models, ORM, templates, auth, REST APIs & deployment for both frameworks

Framework / Backend
Contents
βš™οΈ

Django: Project Setup

# Install & create project
pip install django
django-admin startproject myproject .
python manage.py startapp users
python manage.py startapp posts

# settings.py β€” add apps
INSTALLED_APPS = [
    ...
    "users",
    "posts",
    "rest_framework",  # if using DRF
]

# Run
python manage.py runserver        # http://127.0.0.1:8000
python manage.py migrate          # apply migrations
python manage.py makemigrations   # create migrations
python manage.py createsuperuser  # admin user
python manage.py shell            # interactive shell
πŸ—„οΈ

Django: Models & ORM

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField(blank=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts")
    tags = models.ManyToManyField("Tag", blank=True)
    published = models.BooleanField(default=False)

class Tag(models.Model):
    name = models.CharField(max_length=50, unique=True)

# ── ORM Queries ──
User.objects.all()
User.objects.filter(is_active=True)
User.objects.exclude(name="Admin")
User.objects.get(pk=1)                 # raises DoesNotExist
User.objects.filter(name__icontains="ali")
User.objects.filter(created_at__gte="2024-01-01")
User.objects.order_by("-created_at")[:10]
User.objects.values("name", "email")  # dict queryset
User.objects.count()
User.objects.exists()

# Create / Update / Delete
user = User.objects.create(name="Alice", email="a@b.com")
user.name = "Updated"
user.save()
User.objects.filter(is_active=False).delete()

# Aggregate
from django.db.models import Count, Avg, Q
User.objects.aggregate(total=Count("id"))
User.objects.annotate(post_count=Count("posts"))

# Complex queries with Q
User.objects.filter(Q(name="Alice") | Q(name="Bob"))

# Select related (avoid N+1)
Post.objects.select_related("author").all()         # FK join
Post.objects.prefetch_related("tags").all()          # M2M
🌐

Django: Views & URLs

# urls.py (project)
from django.urls import path, include
urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", include("users.urls")),
]

# users/urls.py
from django.urls import path
from . import views
urlpatterns = [
    path("users/", views.user_list, name="user-list"),
    path("users/<int:pk>/", views.user_detail, name="user-detail"),
]

# Function-based view
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods

@require_http_methods(["GET"])
def user_list(request):
    users = User.objects.values("id", "name", "email")
    return JsonResponse(list(users), safe=False)

# Class-based view
from django.views import View
class UserDetailView(View):
    def get(self, request, pk):
        user = get_object_or_404(User, pk=pk)
        return JsonResponse({"name": user.name})
πŸ“

Django: Forms & Validation

from django import forms

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ["name", "email"]

    def clean_email(self):
        email = self.cleaned_data["email"]
        if not email.endswith("@company.com"):
            raise forms.ValidationError("Must be company email")
        return email

# In view
def create_user(request):
    form = UserForm(request.POST)
    if form.is_valid():
        user = form.save()
        return JsonResponse({"id": user.id})
    return JsonResponse({"errors": form.errors}, status=400)
πŸ”

Django: Authentication

from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User

# Create user
user = User.objects.create_user("alice", "alice@ex.com", "password123")

# Authenticate
user = authenticate(request, username="alice", password="password123")
if user:
    login(request, user)

# Protected view
@login_required
def profile(request):
    return JsonResponse({"user": request.user.username})

# Custom user model (recommended)
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    bio = models.TextField(blank=True)
    avatar = models.URLField(blank=True)
# settings.py: AUTH_USER_MODEL = "users.CustomUser"
πŸš€

Django REST Framework (DRF)

# pip install djangorestframework
from rest_framework import serializers, viewsets, routers

# Serializer
class UserSerializer(serializers.ModelSerializer):
    post_count = serializers.IntegerField(read_only=True)

    class Meta:
        model = User
        fields = ["id", "name", "email", "post_count"]

# ViewSet (full CRUD auto)
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.annotate(post_count=Count("posts"))
    serializer_class = UserSerializer
    filterset_fields = ["is_active"]
    search_fields = ["name", "email"]
    ordering_fields = ["created_at"]

# Router (auto URLs)
router = routers.DefaultRouter()
router.register("users", UserViewSet)
# urlpatterns += router.urls
# GET /users/, POST /users/, GET /users/1/, PUT, PATCH, DELETE
πŸ§ͺ

Flask: Setup & Hello World

# pip install flask
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/")
def hello():
    return jsonify(message="Hello, World!")

if __name__ == "__main__":
    app.run(debug=True, port=5000)

# Project structure
# myapp/
#   __init__.py    (create_app factory)
#   models.py
#   routes/
#     users.py
#     posts.py
#   config.py
πŸ›€οΈ

Flask: Routing & Blueprints

# HTTP methods
@app.route("/users", methods=["GET"])
def get_users():
    return jsonify(users)

@app.route("/users", methods=["POST"])
def create_user():
    data = request.get_json()
    return jsonify(data), 201

# URL parameters
@app.route("/users/<int:user_id>")
def get_user(user_id):
    return jsonify(id=user_id)

# Query params
@app.route("/search")
def search():
    q = request.args.get("q", "")
    page = request.args.get("page", 1, type=int)
    return jsonify(query=q, page=page)

# ── Blueprints (modular routes) ──
# routes/users.py
from flask import Blueprint
users_bp = Blueprint("users", __name__, url_prefix="/api/users")

@users_bp.route("/")
def list_users():
    return jsonify([])

# __init__.py
def create_app():
    app = Flask(__name__)
    from .routes.users import users_bp
    app.register_blueprint(users_bp)
    return app
πŸ—„οΈ

Flask: Database (SQLAlchemy)

# pip install flask-sqlalchemy flask-migrate
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy()
migrate = Migrate()

def create_app():
    app = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://user:pass@localhost/db"
    db.init_app(app)
    migrate.init_app(app, db)
    return app

# Models
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(120), unique=True)
    posts = db.relationship("Post", backref="author", lazy=True)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200))
    user_id = db.Column(db.Integer, db.ForeignKey("user.id"))

# Migrations
# flask db init
# flask db migrate -m "initial"
# flask db upgrade

# Queries
User.query.all()
User.query.filter_by(name="Alice").first()
User.query.filter(User.name.ilike("%ali%")).all()

user = User(name="Bob", email="bob@ex.com")
db.session.add(user)
db.session.commit()
πŸ”

Flask: Auth & JWT

# pip install flask-jwt-extended
from flask_jwt_extended import (
    JWTManager, create_access_token,
    jwt_required, get_jwt_identity
)

app.config["JWT_SECRET_KEY"] = "super-secret"
jwt = JWTManager(app)

@app.route("/login", methods=["POST"])
def login():
    data = request.get_json()
    user = User.query.filter_by(email=data["email"]).first()
    if user and check_password_hash(user.password, data["password"]):
        token = create_access_token(identity=user.id)
        return jsonify(access_token=token)
    return jsonify(error="Invalid credentials"), 401

@app.route("/profile")
@jwt_required()
def profile():
    user_id = get_jwt_identity()
    return jsonify(user_id=user_id)
πŸ§ͺ

Flask: Testing

import pytest
from myapp import create_app

@pytest.fixture
def client():
    app = create_app()
    app.config["TESTING"] = True
    with app.test_client() as client:
        yield client

def test_hello(client):
    response = client.get("/")
    assert response.status_code == 200
    assert response.json["message"] == "Hello, World!"

def test_create_user(client):
    response = client.post("/api/users/",
        json={"name": "Alice", "email": "a@b.com"})
    assert response.status_code == 201
βš–οΈ

Django vs Flask

Aspect Django Flask
Philosophy Batteries-included Micro, pick your own
ORM Built-in (powerful) SQLAlchemy (add-on)
Admin Panel Built-in (excellent) Flask-Admin (add-on)
Auth Built-in Flask-Login / JWT
Best For Large apps, rapid dev Microservices, APIs
Learning Curve Steeper (more concepts) Gentle (minimal API)