Challenge 3: Return the Right Response Type — Possible Solution ==================================================================== # catalog/views.py from django.http import HttpResponse, JsonResponse from django.shortcuts import redirect def plain_text_view(request): return HttpResponse("This is plain text.", content_type="text/plain") def json_view(request): return JsonResponse({"status": "ok", "count": 3}) def redirect_view(request): return redirect("book-list") # redirects to whatever URL "book-list" resolves to # catalog/urls.py from django.urls import path from . import views urlpatterns = [ path("plain/", views.plain_text_view, name="plain-example"), path("json/", views.json_view, name="json-example"), path("go-to-books/", views.redirect_view, name="redirect-example"), ] WHAT EACH RESPONSE ACTUALLY SENDS ----------------------------------- - plain_text_view: an HTTP 200 response with Content-Type: text/plain and the raw string body "This is plain text." - json_view: an HTTP 200 response with Content-Type: application/json and a JSON-encoded body: {"status": "ok", "count": 3} — JsonResponse handles the json.dumps() call and the correct content type automatically. - redirect_view: an HTTP 302 response with a Location header pointing at whatever path the "book-list" named route currently resolves to (per Chapter 2's reverse()/named-URL pattern) — the browser follows this automatically to load /books/ (or wherever that route currently points). WHY THIS WORKS -------------- - Each of these is a thin, explicit wrapper — HttpResponse for raw text/HTML, JsonResponse specifically for JSON, redirect() for a 302 — reinforcing that Django expects you to choose the response type rather than inferring it automatically from what you returned, the way FastAPI infers "this is a dict, so serialize it as JSON." - Using redirect("book-list") (the named-route string) instead of redirect("/books/") ties directly back to Chapter 2 — the redirect target is computed from the URL configuration rather than hardcoded, so it stays correct even if the underlying path changes later. - JsonResponse specifically expects a dict (or an explicit safe=False flag for a list/other JSON-serializable object) — this guardrail exists because early JSON hijacking attacks exploited APIs that returned a bare JSON array at the top level, and Django defaults to the safer behavior.