Chapter 5 of 12
Views are Python functions (or classes) that receive an HTTP request and return an HTTP response. They're the logic layer โ they query models, process data, and pass it to templates.
# courses/views.py
from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse, HttpResponse
from .models import Course
def course_list(request):
"""List all live courses."""
courses = Course.objects.filter(is_live=True).select_related("category")
return render(request, "courses/list.html", {"courses": courses})
def course_detail(request, slug):
"""Show one course by slug."""
# get_object_or_404 โ raises 404 instead of DoesNotExist error
course = get_object_or_404(Course, slug=slug, is_live=True)
return render(request, "courses/detail.html", {"course": course})
# API view โ return JSON instead of HTML
def course_api(request):
courses = Course.objects.filter(is_live=True).values(
"id", "title", "slug", "level"
)
return JsonResponse({"courses": list(courses)})# Django's ORM translates Python to SQL automatically
# Get all courses
Course.objects.all()
# Filter
Course.objects.filter(is_live=True)
Course.objects.filter(level="beginner", is_live=True)
Course.objects.filter(title__icontains="python") # case-insensitive
Course.objects.filter(created_at__year=2025)
Course.objects.exclude(is_live=False)
# Ordering
Course.objects.order_by("-created_at") # - means descending
Course.objects.order_by("title", "-created_at")
# Limit
Course.objects.all()[:10] # first 10
Course.objects.all()[10:20] # next 10 (pagination)
# Single object
Course.objects.get(id=42) # raises DoesNotExist or MultipleObjects
Course.objects.get(slug="nextjs")
# Aggregation
from django.db.models import Count, Avg
Course.objects.aggregate(total=Count("id")) # {"total": 12}
# Create, update, delete
course = Course.objects.create(title="Flask", slug="flask")
course.title = "Flask Framework"
course.save()
Course.objects.filter(is_live=False).update(is_live=True)
Course.objects.filter(id=99).delete()