Django from Basics to Production · Django Fundamentals
Your First Django View
Map URLs to views, return JSON and HTML, and call them with Django's test client, in a single-file Django project.
What you'll build
Two views (a JSON endpoint and an HTML page) wired to URLs, called with Django's test client, which sends requests through the full Django stack without a server. Each example in this course is a complete single-file Django project: the first lines call settings.configure() and register the file as an app named shop, which a real project gets from settings.py and INSTALLED_APPS, and the rest would live in urls.py, views.py and models.py.
The idea
- A view is a function (or class) that takes an
HttpRequestand returns anHttpResponse. - URL patterns (
path("books/<int:pk>/", view)) map paths to views; converters like<int:pk>validate and convert parameters. JsonResponseserialises dictionaries;HttpResponsereturns text or HTML.django.test.Clientmakes requests in-process and is the basis of Django tests.
The code
import sys, types
import django
from django.conf import settings
sys.modules["shop"] = types.ModuleType("shop") # lets this single file act as the "shop" app
sys.modules["shop"].__file__ = __file__
settings.configure(
SECRET_KEY="dev-only", DEBUG=False, ALLOWED_HOSTS=["testserver"], ROOT_URLCONF=__name__,
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth", "shop"],
)
django.setup()
from django.http import Http404, HttpResponse, JsonResponse
from django.urls import path
BOOKS = {1: "Dune", 2: "Emma"}
def book_detail(request, pk):
if pk not in BOOKS:
raise Http404("no such book")
return JsonResponse({"id": pk, "title": BOOKS[pk]})
def home(request):
name = request.GET.get("name", "reader")
return HttpResponse(f"<h1>Hello, {name}</h1>")
urlpatterns = [path("", home), path("books/<int:pk>/", book_detail)]
from django.test import Client
client = Client()
for url in ["/books/2/", "/books/9/", "/books/abc/", "/?name=Ana"]:
r = client.get(url)
body = r.content.decode()[:60] if r.status_code == 200 else "(Django's 404 page)"
print(url, r.status_code, r.headers["Content-Type"].split(";")[0], body)
Output
/books/2/ 200 application/json {"id": 2, "title": "Emma"}
/books/9/ 404 text/html (Django's 404 page)
/books/abc/ 404 text/html (Django's 404 page)
/?name=Ana 200 text/html <h1>Hello, Ana</h1>Run this on your computer — see “Get Started” for setup.
Common mistakes
- Building HTML with f-strings and user input (as in this tiny example's
name): use templates, which escape automatically (see the templates lesson). DEBUG = Truein production, which exposes settings and code in error pages.- Forgetting
ALLOWED_HOSTS, so every request gets a 400 in production.
Key points
- Views take a request and return a response; URLs map paths to views.
- Path converters validate parameters (
/books/abc/never reaches the view). - The test client exercises the full stack without a server.
Further reading: Writing views · URL dispatcher
Practice questions
What does the <int:pk> path converter do?
Answer
It matches only digits and passes the value to the view as an int; non-numeric paths don't match the pattern and get a 404.
Why must DEBUG be False in production?
Answer
Debug error pages reveal settings, code, SQL and environment details, and Django keeps extra debugging data in memory.
What does Django's test Client do?
Answer
It sends requests through URL routing, middleware and views in-process, returning the response for assertions, without running a server.
Open in the app to mark lessons complete, take notes and track your progress.