views.py#
What is views.py?#
- views.py answers this question:
“When a URL is requested, what should Django do and what should it return?”
- A view:
Receives a request
Runs Python logic
Returns a response
Django Flow
Browser
↓
urls.py
↓
views.py
↓
Response (HTML / JSON / Text)
Types of Views in Django#
- There are two main types:
Function-Based Views (FBV) beginner-friendly
Class-Based Views (CBV) scalable & reusable
We’ll start with Function-Based Views.
1) Function-Based Views (FBV)#
What an FBV is
- An FBV is simply a Python function that:
receives a request object
does some logic
returns a HttpResponse (or JsonResponse, or render())
FBV shape (always the same)
def my_view(request, ...):
# 1) read request data (GET/POST/headers/user)
# 2) do logic (DB query, validation, etc.)
# 3) return response
A) Basic FBV examples
Return plain text
from django.http import HttpResponse
def home(request):
return HttpResponse("Hello from FBV")
Return HTML template
from django.shortcuts import render
def home(request):
return render(request, "myapp/home.html")
Return JSON (API style)
from django.http import JsonResponse
def status(request):
return JsonResponse({"ok": True, "message": "Server is running"})
B) Reading request data in FBV
Query string: ?q=phone
def search(request):
q = request.GET.get("q", "") # GET parameters
return HttpResponse(f"You searched: {q}")
Form POST data
def submit(request):
if request.method == "POST":
name = request.POST.get("name")
return HttpResponse(f"Received: {name}")
return HttpResponse("Send a POST request")
C) CRUD example with FBV
Suppose you have a model Post.
from django.shortcuts import render, redirect, get_object_or_404
from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, "myapp/post_list.html", {"posts": posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, "myapp/post_detail.html", {"post": post})
def post_create(request):
if request.method == "POST":
title = request.POST.get("title")
Post.objects.create(title=title)
return redirect("post_list")
return render(request, "myapp/post_form.html")
Easy to read.
Repetition grows when you build many CRUD pages.
D) Pros / Cons of FBV
- Pros
Very easy to learn and debug
Straight-line logic, clear flow
Great for small pages and custom logic
- Cons
Repetition for common CRUD patterns
Harder to reuse behavior across many views
You manually handle GET/POST patterns again and again
2) Class-Based Views (CBV) — scalable & reusable#
What a CBV is
- A CBV is a Python class where each HTTP method is a method:
get() handles GET
post() handles POST
put(), delete() etc.
You connect it in urls.py using .as_view().
A) Basic CBV example
from django.views import View
from django.http import HttpResponse
class HomeView(View):
def get(self, request):
return HttpResponse("Hello from CBV")
urls.py
from django.urls import path
from .views import HomeView
urlpatterns = [
path("", HomeView.as_view(), name="home"),
]
as_view() converts the class into a callable view function Django can run.
B) Why CBV feels “powerful”
- Because CBVs can be built using:
inheritance
mixins
generic views (ListView, DetailView, CreateView…)
This reduces code and repetition massively.
The most important CBVs: Generic Views
1) ListView (list objects)
from django.views.generic import ListView
from .models import Post
class PostListView(ListView):
model = Post
template_name = "myapp/post_list.html"
context_object_name = "posts"
That’s it. Django does the query + context + render.
2) DetailView (one object)
from django.views.generic import DetailView
from .models import Post
class PostDetailView(DetailView):
model = Post
template_name = "myapp/post_detail.html"
context_object_name = "post"
3) CreateView (create object)
from django.views.generic import CreateView
from django.urls import reverse_lazy
from .models import Post
class PostCreateView(CreateView):
model = Post
fields = ["title", "body"]
template_name = "myapp/post_form.html"
success_url = reverse_lazy("post_list")
4) UpdateView / DeleteView
They work the same way. Very clean.
C) Handling logic in CBV (override methods)
Example: filter posts by query param
class PostListView(ListView):
model = Post
template_name = "myapp/post_list.html"
def get_queryset(self):
qs = super().get_queryset()
q = self.request.GET.get("q")
if q:
qs = qs.filter(title__icontains=q)
return qs
D) Mixins (reusable behavior)
Mixins are “plugins” you add to CBVs.
Example: login required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
class PrivatePostListView(LoginRequiredMixin, ListView):
model = Post
Now only logged-in users can access.
E) Pros / Cons of CBV
- Pros
Less repetition, especially for CRUD
Clean, scalable for big apps
Mixins allow reusable features (auth, permissions, etc.)
Generic views save lots of code
- Cons
Harder at the beginning
Inheritance chain can confuse (where did this behavior come from?)
Debugging sometimes needs deeper understanding
FBV vs CBV
Feature |
FBV |
|---|---|
CBV |
Learning |
âś… easiest |
⚠️ medium |
CRUD speed |
❌ more code |
âś… very fast |
Reuse |
❌ manual |
âś… mixins/inheritance |
Clarity |
âś… direct |
⚠️ sometimes hidden |
Best for |
small/custom logic |
big scalable apps |
When to choose what?#
- Choose FBV when:
You’re learning
The view is simple and custom
You need full control without “magic”
- Choose CBV when:
You have many pages with similar patterns (CRUD)
You want scalable organization
You need mixins (auth/permissions) a lot