Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Models, Views, Admin and Tests  ›  Lesson

Function-Based Views

Function-based views 15 minA function-based view in views.py takes an HttpRequest and must return an HttpResponse, usually by fetching data and rendering a template with render().

Function-Based Views

The URL patterns have picked a view. Now your code finally runs. A view is where the cookbook decides what to show: which recipes, in what order, with which template. The simplest kind of view is an ordinary Python function, and it has one strict contract.

The rule

Request in, response out: a view must always return an HttpResponse.

The smallest possible view:

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello from the cookbook")

Django calls it with an HttpRequest as the first argument, plus anything the URL captured. The request holds what the browser sent: request.method ("GET", "POST"), request.GET (query string values), request.POST (form data) and request.user.

Real views rarely build HTML by hand. They fetch data and hand it to a template with render():

# recipes/views.py
from django.shortcuts import get_object_or_404, render
from .models import Recipe

def recipe_list(request):
    query = request.GET.get("q", "")
    recipes = Recipe.objects.filter(title__icontains=query).order_by("-created")
    return render(request, "recipes/recipe_list.html", {"recipes": recipes, "q": query})

def recipe_detail(request, slug):
    recipe = get_object_or_404(Recipe, slug=slug)
    return render(request, "recipes/recipe_detail.html", {"recipe": recipe})
  • render(request, template, context) fills the template with the dictionary and returns an HttpResponse.
  • get_object_or_404 returns the object, or raises Http404, which Django turns into a proper 404 page instead of a crash.
  • Templates live in recipes/templates/recipes/...; the repeated folder name keeps them apart from other apps' templates.

Other returns you will use: redirect("recipes:detail", slug=...) after saving something, and JsonResponse({...}) for data.

To handle a form, one view can branch on the method:

def recipe_new(request):
    if request.method == "POST":
        ...   # validate, save, then return redirect(...)
    return render(request, "recipes/recipe_form.html")

The shortcut

Write every view as three lines in your head: get input → get data → return a response. If any path through the function can end without a return, it is a bug.

/recipes/?q=soupStep 1 of 4
  1. Get input

    request.GET.get("q", "") gives "soup", or an empty string if absent.

Forget the return on some branch and Django complains that the view "didn't return an HttpResponse object. It returned None instead."

Drills

Answer fast — trust the rule.

quick drill

What must every Django view return?

quick drill

For /recipes/no-such-dish/, what does get_object_or_404(Recipe, slug=slug) lead to?

quick drill

How does a view read q from /recipes/?q=soup?

quick drill

In render(request, "recipes/recipe_list.html", {"recipes": recipes}), what is the dictionary?

Remember

  • Request in, response out: every path returns an HttpResponse.
  • Get input, get data, return a response.
  • Trap: a branch without return, and hand-built HTML instead of render().

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWrite the detail view

Write the recipe_detail view for /recipes// and explain every line: what it receives, how it fetches the recipe, what happens when the slug does not exist, and what it must return.