Django Pocket Book

Django Pocket Book — Uplatz

50 deep-dive flashcards • Wide layout • Fewer scrolls • 20+ Interview Q&A • Readable code examples

Section 1 — Fundamentals

1) What is Django?

Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. It follows the MTV (Model–Template–View) architecture, ships with an ORM, admin, authentication, forms, and security protections out of the box. Sweet spots: data-driven apps, dashboards, CMS/CRUD, APIs with DRF. For ultra-low-latency microservices, consider lighter stacks — but Django scales well with proper caching, DB tuning, and async where appropriate.

# Check your Django & Python
python -V
python -m django --version

2) Why Django? Core Strengths & Tradeoffs

Strengths: batteries-included, stable APIs, secure defaults (CSRF, XSS, clickjacking), powerful admin, robust ORM and migrations. Tradeoffs: opinionated structure, heavier than microframeworks, template-first by default. Mitigate with modular apps, environment-driven settings, and selective third-party packages.

# Create a project quickly
python -m venv .venv && source .venv/bin/activate
pip install django
django-admin startproject config .
python manage.py startapp core

3) Request–Response Lifecycle: Mental Model

Incoming request → URL resolver → middleware stack → view → ORM/templates → response → middleware (outbound) → server. Know where auth, sessions, and CSRF run, and how streaming responses bypass template rendering. Use this to reason about where to log, cache, or short-circuit work.

# urls.py
from django.urls import path
from core.views import ping
urlpatterns = [ path("health/", ping) ]

Map URLs early; keep views slim; push heavy work to services/tasks.

4) WSGI vs ASGI

WSGI powers classic sync Django; ASGI enables async views, long-lived connections, and websockets (via Channels). Django runs in both; mixing sync DB work in async views creates thread hops — keep DB operations in sync contexts or use async drivers judiciously.

# asgi.py (generated by startproject)
from django.core.asgi import get_asgi_application
application = get_asgi_application()

5) Django vs Flask/FastAPI

Django: full-stack with ORM, admin, auth, forms; great for CRUD and teams. Flask: micro, flexible, bring-your-own libs. FastAPI: async-first, typed schemas via Pydantic, great for APIs. Choose Django when you want batteries and convention; integrate DRF for APIs.

# Install DRF for Django APIs
pip install djangorestframework
# settings.py
INSTALLED_APPS += ["rest_framework"]

6) pip, venv, Poetry

Use virtual environments to isolate deps; pin versions with pip-tools or Poetry. Commit lock files for reproducible deploys and mirror your prod Python version locally.

pip install "django<=5.1" pip-tools
pip-compile requirements.in
pip-sync requirements.txt

7) settings.py & Env Config

Settings vary by environment. Keep secrets out of VCS and validate required env vars on boot. Split settings into modules or use django-environ/pydantic-settings for typed config.

# settings.py
import environ; env = environ.Env(DEBUG=(bool, False))
DEBUG = env("DEBUG")
ALLOWED_HOSTS = env.list("ALLOWED_HOSTS", default=[])

8) LTS vs Latest

Django publishes LTS releases with extended support. Prefer LTS for long-lived products; test against the latest in CI to prepare for upgrades. Upgrade minor releases frequently for security fixes.

# Pin version
echo "Django==5.0.*" >> requirements.in
pip-compile && pip-sync

9) pyenv & Multi-Version Dev

Install multiple Python versions with pyenv and per-project .python-version. Align CI and prod. Use tox to test across supported Python/Django matrices.

pyenv install 3.12.5
pyenv local 3.12.5

10) Q&A — “Is Django synchronous or asynchronous?”

Answer: Both. Django supports sync (WSGI) and async (ASGI) entry points. Views can be def or async def; middleware likewise. DB backends are primarily sync, so async views doing ORM work hop to threads. For websockets/long I/O, use ASGI + Channels.

Section 2 — Core APIs & Modules

11) URLconf & Routing

Define URL patterns with path and re_path. Keep project urls.py thin and include app routes. Name your URLs for reverse lookups in templates and redirects.

# core/urls.py
from django.urls import path
from . import views
urlpatterns = [ path("hello/", views.hello, name="hello") ]

12) Models & ORM Essentials

Django models map to tables; fields map to columns with validation. Use constraints, unique indexes, and choices enums. Keep business logic in model methods/managers.

# core/models.py
from django.db import models
class User(models.Model):
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)

13) Views & HttpResponse

Function-based views (FBV) are simple; class-based views (CBV) provide reuse. Always return HttpResponse/JsonResponse and handle methods explicitly.

# core/views.py
from django.http import JsonResponse
def hello(_):
    return JsonResponse({"ok": True})

14) QuerySets & Managers

QuerySets are lazy, chainable, and composable. Push filtering/ordering to DB. Use .only()/.defer() to trim columns; write custom managers for common scopes.

from core.models import User
users = User.objects.filter(email__endswith="@example.com").order_by("-created_at")

15) Migrations

Migrations track schema changes. Run makemigrations then migrate. Use RunPython for data migrations; keep them idempotent and reversible.

python manage.py makemigrations
python manage.py migrate

16) Admin Customization

The admin offers instant CRUD. Register models, customize list displays, actions, and fieldsets. Lock down access with staff/superuser and permissions.

# core/admin.py
from django.contrib import admin
from .models import User
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    list_display = ("email","created_at")

17) Forms & ModelForms

Forms validate user input; ModelForms tie to models. Prefer server-side validation even when using JS. Use clean_* methods for field logic.

from django import forms
from .models import User
class UserForm(forms.ModelForm):
    class Meta: model = User; fields = ["email"]

18) Middleware

Middleware wraps requests/responses (security, sessions, auth). Keep it fast and stateless. Use it for cross-cutting concerns (headers, logging), not business logic.

# settings.py
MIDDLEWARE += ["django.middleware.security.SecurityMiddleware"]

19) Static & Media Files

Collect static assets with collectstatic to a single location for serving via CDN/Whitenoise. Store user uploads on S3/Cloud Storage with signed URLs.

# settings.py
STATIC_URL = "/static/"; MEDIA_URL = "/media/"
STATIC_ROOT = BASE_DIR / "staticfiles"

20) Q&A — “FBV or CBV?”

Answer: Use FBV for simple endpoints; switch to CBV when you benefit from mixins (ListView, CreateView) or need reuse/overrides. For APIs, DRF viewsets mix in auth, throttling, and serialization ergonomically.

Section 3 — Async, Patterns & Concurrency

21) Async Views

Django supports async def views/middleware. Use for I/O-bound work (HTTP calls) with httpx. Database ORM is sync; avoid mixing long async with blocking DB calls.

# async view
from django.http import JsonResponse
import httpx
async def joke(_):
    async with httpx.AsyncClient(timeout=2) as c:
        r = await c.get("https://api.example.com")
    return JsonResponse(r.json())

22) Class-Based Views Patterns

Leverage mixins (LoginRequiredMixin, CRUD mixins) to DRY up common behavior. Override get_queryset/form_valid selectively. Keep templates cohesive with CBV context.

from django.views.generic import ListView
from .models import User
class UserList(ListView): model = User; paginate_by = 20

23) Transactions & Atomicity

Use @transaction.atomic to bundle operations; avoid partial writes. For idempotency, guard unique constraints and handle IntegrityError cleanly.

from django.db import transaction
@transaction.atomic
def create_user(email):
    ...

24) select_related vs prefetch_related

select_related joins on FK/OneToOne, prefetch_related issues separate queries and stitches in Python for M2M/reverse. Use the right one to kill N+1 queries.

User.objects.select_related("profile").prefetch_related("groups")

25) Celery for Background Jobs

Offload CPU/slow I/O to Celery workers (Redis/RabbitMQ broker). Add retries with exponential backoff and dead-letter queues; keep tasks idempotent.

# tasks.py
from celery import shared_task
@shared_task(bind=True, max_retries=3)
def send_email_task(user_id): ...

26) Channels & WebSockets

Django Channels brings websockets and background consumers atop ASGI. Use Redis as the channel layer; scale horizontally with sticky sessions or shared layer.

# asgi.py includes ProtocolTypeRouter
# routing.py maps websocket URL patterns to consumers

27) Caching in Practice

Use per-view, template fragment, or low-level caching. Backends: LocMem (dev), Memcached, Redis. Add cache keys with versioning and invalidate on writes.

from django.views.decorators.cache import cache_page
@cache_page(60)  # 60s
def stats(request): ...

28) Rate Limits & Throttling

For APIs, DRF throttles per user/IP. For sites, django-ratelimit helps guard forms and auth. Always return 429 with hints.

# DRF settings
REST_FRAMEWORK = { "DEFAULT_THROTTLE_RATES": { "anon":"100/hour","user":"1000/hour" } }

29) External Calls: Timeouts & Retries

Always set timeouts, use exponential backoff with jitter, and bound concurrency. Wrap calls and surface metrics.

import httpx, backoff
@backoff.on_exception(backoff.expo, httpx.HTTPError, max_time=8)
def fetch(url): return httpx.get(url, timeout=2)

30) Q&A — “Celery vs cron?”

Answer: Use Celery for distributed, retryable tasks, scheduled or on-demand, with result tracking. Use system cron for simple, single-host jobs with no retries/state. Many teams use Celery beat (or Django-Q/RQ) for schedules.

Section 4 — Frameworks, Data & APIs

31) Django REST Framework (DRF)

DRF adds serializers, viewsets, routers, browsable API, throttles, and auth. Define explicit schemas and use generics for CRUD to move fast.

# api/views.py
from rest_framework import viewsets, serializers
from core.models import User
class UserSer(serializers.ModelSerializer):
    class Meta: model = User; fields = ["id","email"]
class UserView(viewsets.ModelViewSet):
    queryset = User.objects.all(); serializer_class = UserSer

32) DRF Routers & Permissions

Routers auto-wire CRUD endpoints. Apply IsAuthenticated/DjangoModelPermissions and per-action overrides. Add pagination and filtering.

# api/urls.py
from rest_framework.routers import DefaultRouter
from .views import UserView
router = DefaultRouter(); router.register("users", UserView)
urlpatterns = router.urls

33) GraphQL with Graphene

Graphene integrates Django models into GraphQL schemas. Add complexity/depth limits, and batch N+1 with graphene-django-optimizer.

# schema.py
import graphene
class Query(graphene.ObjectType):
    hello = graphene.String()
    def resolve_hello(root, info): return "world"

34) REST Design (DRF)

Use nouns, filtering, pagination, and proper status codes. Validate with serializers; document with OpenAPI/Swagger (drf-spectacular/drf-yasg).

# settings.py
REST_FRAMEWORK = { "DEFAULT_SCHEMA_CLASS":"drf_spectacular.openapi.AutoSchema" }

35) Serialization & Validation

Prefer ModelSerializer for CRUD; write custom validate_* and validate for cross-field logic. Keep serializers slim; avoid heavy side-effects in create/update.

class RegisterSer(serializers.Serializer):
    email = serializers.EmailField()

36) Real-Time with Channels

Use groups to broadcast events, auth via tokens/sessions, and back messages with Redis. For presence, expire keys with TTL.

# consumer skeleton
from channels.generic.websocket import AsyncWebsocketConsumer
class Chat(AsyncWebsocketConsumer): ...

37) PostgreSQL Tips

Use strong constraints, composite indexes, and EXPLAIN ANALYZE. Prefer UUID PKs (django.contrib.postgres extras), and transactions for bulk writes.

# settings.py
DATABASES["default"]["CONN_MAX_AGE"] = 60

38) Search Integration

For simple needs, use icontains/trigram similarity. For full-text, wire Elasticsearch or OpenSearch using django-elasticsearch-dsl.

# example: trigram extension (Postgres)
# CREATE EXTENSION pg_trgm;

39) i18n & l10n

Mark strings for translation, compile messages, and detect language via middleware. Localize dates/numbers in templates.

{% load i18n %}
{% trans "Hello" %}

40) Q&A — “REST or GraphQL?”

Answer: REST is simpler and CDN-friendly; DRF gives you CRUD fast. GraphQL shines for complex UIs needing flexible shapes. Many teams expose REST publicly and use GraphQL internally.

Section 5 — Security, Testing, Deployment, Observability & Interview Q&A

41) Security Fundamentals

Django ships CSRF, XSS, and clickjacking protection. Enforce HTTPS, HSTS, secure cookies, strict ALLOWED_HOSTS, and rotated secrets. Validate all input server-side.

# settings.py
SECURE_HSTS_SECONDS = 31536000
SESSION_COOKIE_SECURE = CSRF_COOKIE_SECURE = True

42) Auth, Users & Permissions

Use the pluggable user model from day one. Leverage groups/permissions, per-object perms, and DRF permission classes. Rotate sessions on privilege changes.

# settings.py
AUTH_USER_MODEL = "core.User"

43) Testing Strategy

Use pytest-django for fast tests, factories for fixtures, and RequestFactory/APIClient for views. Mix unit/integration; use a dedicated test DB with migrations faked when speed matters.

pip install pytest pytest-django
pytest -q

44) Linting, Formatting & Types

Adopt Black, Ruff/Flake8, isort, and mypy with django-stubs. Run in CI (pre-commit) and keep type hints in services, serializers, and utils.

pip install black ruff mypy django-stubs pre-commit
pre-commit install

45) Performance & Profiling

Measure with Django Debug Toolbar, Silk, and query logs. Kill N+1 with prefetch/select, use caching, and paginate aggressively. Template fragment cache hot components.

# Example: log slow queries in dev
LOGGING = { "handlers": ..., "loggers": {"django.db.backends": {"level":"DEBUG"}} }

46) Deployment Options

WSGI: Gunicorn + Nginx. ASGI: Uvicorn/Daphne. Serve static via CDN/Whitenoise. Use container images pinned to Python, run health checks, and graceful shutdown.

# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn","config.wsgi:application","-b","0.0.0.0:8000","-w","3"]

47) Observability

Structured logging (JSON), request IDs, APM (Sentry/Elastic APM), metrics (Prometheus + django-prometheus), and tracing (OpenTelemetry). Expose health/readiness endpoints.

pip install sentry-sdk
import sentry_sdk; sentry_sdk.init(dsn=..., traces_sample_rate=0.2)

48) Prod Checklist

  • Env-driven settings & secrets manager
  • HTTPS, HSTS, CSRF, secure cookies
  • Sane timeouts for external calls
  • DB connections pooled; indexes verified
  • Caching: per-view/fragment + CDN
  • Alerting on error rate/latency/SLOs

49) Common Pitfalls

Doing heavy work in requests (no task queue), N+1 queries, storing files locally in ephemeral containers, missing ALLOWED_HOSTS/secure cookies, and ignoring migrations conflicts. Prevent with reviews, linters, tests, and observability.

50) Interview Q&A — 20 Practical Questions (Expanded)

1) Why Django for CRUD apps? Batteries-included ORM/admin/forms/security accelerate delivery while keeping consistency.

2) MTV vs MVC? Django’s View handles “controller” logic; Templates are the “view”; Models match models — terminology difference, same separation.

3) Sync vs async? Django supports both; use ASGI for websockets/long I/O; most DB work is sync.

4) Kill N+1? Use select_related/prefetch_related, annotate counts, and profile queries.

5) Custom user model? Create on day one to avoid migration pain; swap AUTH_USER_MODEL.

6) Where to put business logic? Services/domain modules or model methods/managers; keep views thin.

7) Forms vs serializers? Forms for HTML; DRF serializers for APIs; both validate.

8) Static vs media? Static = versioned assets; media = user uploads; serve via CDN/object storage.

9) CSRF on APIs? Use session-based CSRF for browser clients; for token/JWT APIs, exempt and rely on CORS + auth.

10) Caching strategy? Layered: per-view/fragment, Redis/Memcached, CDN; invalidate on writes.

11) DRF auth? Session for same-site, Token/JWT for APIs; apply permission classes and throttles.

12) File uploads? Use storage backends (S3) with signed URLs; avoid serving from app containers.

13) Signals usage? For decoupled side-effects (audit), but don’t hide core business flows.

14) Migrations conflicts? Rebase and --empty/--merge when necessary; keep migrations small.

15) Multi-tenant? Separate schemas/dbs, or row-level scoping with constraints and queries.

16) Handling long tasks? Celery workers + beat schedules; expose task IDs and status.

17) Serving at scale? Gunicorn/Uvicorn behind Nginx, autoscale containers, shared cache/DB, and health checks.

18) Env management? django-environ or typed settings; never commit secrets.

19) Templates vs Jinja2? Django templates are safe and integrated; Jinja2 is faster/flexible — pick per project.

20) Monitoring? Sentry for errors, Prometheus for metrics, logs with request IDs, and alerts on SLO burn.