Learning Python - Web Frameworks & API Design
Series/Learn Python/Episode 13
Episode 13 of 23

Learning Python - Web Frameworks & API Design

This episode builds a real API: comparing Flask, Django, and FastAPI and when to choose each one. You'll also learn to design RESTful and GraphQL APIs, including versioning, pagination, and input validation.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

After mastering networking in episode 12, now it's time to build the server side. Episode 13 compares the three most popular Python web frameworks — Flask, Django, and FastAPI — and teaches you how to design good APIs.

We'll build a real FastAPI application, design RESTful and GraphQL, and apply versioning, pagination, and input validation — skills you'll use directly in the workplace.

Comparing Flask, Django, and FastAPI

Flask: A Micro-Framework

Flask is minimal and flexible, great for small APIs and prototypes:

Install Flask
pip install flask
PythonFlask minimal
from flask import Flask, jsonify
 
app = Flask(__name__)
 
@app.route("/halo")
def halo():
    return jsonify({"pesan": "Halo Flask"})

@app.route("/halo") connects a URL to a function. Flask gives you full freedom to choose components, but the structure responsibility is on you. Good for small projects that need total control.

Django: Batteries Included

Django provides everything — ORM, admin, auth — in a single framework:

Membuat project Django
pip install django
django-admin startproject belajardjango
cd belajardjango
python3 manage.py runserver

django-admin startproject belajardjango creates a project with a complete structure. Django excels at large web applications that need many built-in features: admin panel, authentication, and migrations come for free.

FastAPI: Modern and Async

FastAPI combines Python types, automatic validation, and async performance:

Install FastAPI
pip install "fastapi[standard]"
PythonFastAPI minimal
from fastapi import FastAPI
 
app = FastAPI()
 
@app.get("/halo")
def halo():
    return {"pesan": "Halo FastAPI"}

@app.get("/halo") defines an endpoint. FastAPI uses Python types for validation and automatic documentation. It's the top choice for new APIs and microservices in the modern era.

Designing a RESTful API

REST Principles

REST (Representational State Transfer) uses resources and HTTP methods:

PythonEndpoint REST dasar
from fastapi import FastAPI
 
app = FastAPI()
produk = {}
 
@app.get("/produk")
def daftar_produk():
    return produk
 
@app.post("/produk/{id_produk}")
def tambah_produk(id_produk: int, nama: str):
    produk[id_produk] = nama
    return {"id": id_produk, "nama": nama}

@app.get("/produk") retrieves the list, @app.post("/produk/{id_produk}") adds data. REST uses nouns for resources and HTTP methods as actions. Endpoint names should be plural and consistent.

Input Validation with Pydantic

Why Validation Matters

Input validation prevents corrupt data from entering the system and is a security foundation. FastAPI uses pydantic for this:

PythonModel Pydantic untuk validasi
from fastapi import FastAPI
from pydantic import BaseModel, Field
 
app = FastAPI()
 
class Produk(BaseModel):
    nama: str = Field(min_length=1, max_length=100)
    harga: int = Field(gt=0)
 
@app.post("/produk")
def buat_produk(data: Produk):
    return data

class Produk(BaseModel) defines a schema with constraints. Field(min_length=1, max_length=100) and Field(gt=0) validate automatically. If input is invalid, FastAPI returns 422 with error details — no need to write manual validation code.

Versioning and Pagination

API Versioning

APIs change over time. Versioning protects existing clients:

PythonAPI dengan versioning
from fastapi import FastAPI
 
app_v1 = FastAPI()
app_v2 = FastAPI()
 
@app_v1.get("/produk")
def daftar_v1():
    return {"versi": "v1"}
 
@app_v2.get("/produk")
def daftar_v2():
    return {"versi": "v2", "paginated": True}

Creating a separate app per version is one approach. Another is using URL prefixes /api/v1 and /api/v2. Versioning gives clients time to migrate as the API evolves.

GraphQL: An Alternative Approach

Understanding GraphQL

GraphQL lets clients request the specific data they need, unlike REST which returns a fixed structure:

PythonGraphQL dengan strawberry
import strawberry
 
@strawberry.type
class Produk:
    id: int
    nama: str
 
@strawberry.type
class Query:
    @strawberry.field
    def produk(self, id: int) -> Produk:
        return Produk(id=id, nama="Contoh")
 
schema = strawberry.Schema(query=Query)
print(schema.as_str()[:50])

@strawberry.type defines a GraphQL type and @strawberry.field defines a query. Clients can pick the fields they ask for, reducing over-fetching. GraphQL suits applications with many clients and diverse data needs.

Closing

Key takeaways:

  • Flask is minimal and flexible; Django is complete; FastAPI is modern and async.
  • FastAPI uses Python types for validation and automatic documentation.
  • REST uses resources and HTTP methods with plural names.
  • Pydantic validates input with Field constraints.
  • Versioning protects clients as the API evolves.
  • GraphQL lets clients request specific data and reduces over-fetching.

In the next episode, episode 14, we'll cover security best practices — secure coding with input validation and escaping, injection prevention, authentication and authorization patterns with JWT and OAuth2, CSRF and CORS protection, and dependency security scanning. Your API will become secure!

Learning Python - Web Frameworks & API Design | Learn Python