In this lesson we’ll make Django think and respond:
- Build function-based views (FBVs)
- Return HTML, JSON, and redirects
- Pass data from views to templates
- Create a random poem view
We’ll use your existing project:
- Project:
hello_django - Main folder:
config - Apps:
home,blog - Port:
8011
(So URLs look like:http://your-server-ip:8011/...)
Throughout the lesson I’ll highlight “Common mistake” boxes to help you avoid typical beginner errors.
1. What is a View?
A view is a Python function that:
- Receives a request (
request) - Returns a response (
HttpResponse, template, JSON, redirect, etc.)
Basic shape:
def my_view(request):
return HttpResponse("Hello from a view!")
Views live in each app’s views.py:
home/views.pyblog/views.py
2. Home App Views (HTML + Redirect)
We’ll start with the home app: the root page /, /about/, and a redirect /go-about/.
2.1. Update home/views.py
Open:
home/views.py
and make sure it looks like this:
from django.http import HttpResponse
from django.shortcuts import render, redirect # ✅ VERY IMPORTANT IMPORTS
def home_page(request):
return HttpResponse("<h1>Welcome to Hello Django!</h1>")
def about_page(request):
# This will look for templates/home/about.html
return render(request, "home/about.html")
def go_to_about(request):
# Redirect to the URL named "about"
return redirect("about")
🧠 Common mistake #1 – “NameError: ‘render’ is not defined”
Always importrender(andredirect) fromdjango.shortcutsat the top of the file:from django.shortcuts import render, redirect
2.2. Home URLs – home/urls.py
Now connect these views to URLs.
Open (or create):
home/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.home_page, name="home"), # /
path("about/", views.about_page, name="about"), # /about/
path("go-about/", views.go_to_about, name="go-about"), # /go-about/
]
🧠 Common mistake #2 – URL points to non-existent view
If you writeviews.go_to_aboutbut your function is namedgo_about, you’ll get:AttributeError: module 'home.views' has no attribute 'go_to_about'.
✅ Make sure the function name in the URL matches the function name inviews.pyexactly.
2.3. Include home.urls in the Project URLs
This should already be done from previous lessons, but confirm that:
config/urls.py contains:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('home.urls')), # root URLs from home app
path('blog/', include('blog.urls')) # blog URLs under /blog/
]
Now test:
http://your-server-ip:8011/→ “Welcome to Hello Django!”http://your-server-ip:8011/about/→ template pagehttp://your-server-ip:8011/go-about/→ redirects to/about/
🧠 Common mistake #3 – Redirect fails
If you seeNameError: 'redirect' is not defined, you forgot:from django.shortcuts import redirect
3. Blog App – Poem Detail & List Views
Now we’ll work in the blog app and create:
- A poem detail view:
/blog/poems/1/ - A poem list view:
/blog/poems/
3.1. Update blog/views.py
Open:
blog/views.py
import random
from django.shortcuts import render
from django.http import JsonResponse
def poem_detail(request, id):
"""
Simple detail view that just shows the poem ID.
Later we will connect this to a real database.
"""
return render(request, "blog/poem_detail.html", {"id": id})
def poem_list(request):
"""
Pass a list of poem titles to the template.
"""
poems = ["Poem One", "Poem Two", "Poem Three"]
return render(request, "blog/poems.html", {"poems": poems})
def random_poem(request):
"""
Homework view – shows a random poem.
"""
poems = [
"The sun rises on ancient hills.",
"Whispers of wind echo in the valley.",
"Lonely stars guard the night sky.",
"Dreams fall like rain on silent earth."
]
poem = random.choice(poems)
return render(request, "blog/random_poem.html", {"poem": poem})
def sample_json(request):
"""
Simple JSON API-style response.
"""
data = {
"name": "Omar",
"language": "Django",
"status": "Learning Views"
}
return JsonResponse(data)
🧠 Common mistake #4 – “module ‘blog.views’ has no attribute ‘poem_detail’”
This happens when your URL saysviews.poem_detailbut you never created the function.
✅ Always create the view function before wiring it inurls.py.
3.2. Blog URLs – blog/urls.py
Open:
blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("poems/", views.poem_list, name="poem_list"), # /blog/poems/
path("poems/<int:id>/", views.poem_detail, name="poem_detail"),# /blog/poems/1/
path("random-poem/", views.random_poem, name="random_poem"), # /blog/random-poem/
path("api/info/", views.sample_json, name="sample-json"), # /blog/api/info/
]
🧠 Common mistake #5 – 404 on
/blog/poems/
If Django shows a 404 and the error page lists onlyblog/poems/<int:id>/but notblog/poems/, it means you forgot:path("poems/", views.poem_list, name="poem_list")
4. Templates for the Blog Views
Create these files:
4.1. blog/templates/blog/poem_detail.html
<h1>Poem Detail Page</h1>
<p>Poem ID: {{ id }}</p>
<p>(Later we will load the poem from the database.)</p>
4.2. blog/templates/blog/poems.html
<h1>Poem List</h1>
<ul>
{% for poem in poems %}
<li>{{ poem }}</li>
{% endfor %}
</ul>
4.3. blog/templates/blog/random_poem.html
<h1>Your Random Poem</h1>
<p>{{ poem }}</p>
<p>Refresh the page to get another one!</p>
And for the home about page:
4.4. home/templates/home/about.html
<h1>About This Site</h1>
<p>This page is rendered from a template using Django's render() function.</p>
5. JSON Response – First Step Toward APIs
Your JSON view is already a tiny API:
def sample_json(request):
data = {
"name": "Omar",
"language": "Django",
"status": "Learning Views"
}
return JsonResponse(data)
Because blog/urls.py is included under path('blog/', include('blog.urls')) in config/urls.py, the full URL is:
http://your-server-ip:8011/blog/api/info/
🧠 Common mistake #6 – 404 on
/api/info/
If you go to/api/info/you get 404 because the route is under/blog/.
✅ Always remember the app prefix. For this project:
- Home URLs:
/and/about/etc.- Blog URLs:
/blog/...
6. Homework – Random Poem View (You Already Built It!)
Goal: Create a view that displays a random poem.
We already included the solution above:
- View:
random_poeminblog/views.py - URL:
path("random-poem/", views.random_poem, name="random_poem") - Template:
blog/random_poem.html
Final URL in browser:
http://your-server-ip:8011/blog/random-poem/
Refresh the page to see different poems.
7. Checklist – Avoiding Errors
Before you move to the next lesson, confirm:
✔ Imports
home/views.pyhas:from django.http import HttpResponse from django.shortcuts import render, redirectblog/views.pyhas:import random from django.shortcuts import render from django.http import JsonResponse
✔ URLs and Views Match
- Every
views.Xinhome/urls.pyandblog/urls.pyhas a matching functiondef X(...)in the correctviews.py. config/urls.pyincludes both:path('', include('home.urls')), path('blog/', include('blog.urls')),
✔ Paths You Can Visit
/→ home text/about/→ About template/go-about/→ redirects to/about//blog/poems/→ poem list/blog/poems/1/→ poem detail with ID/blog/random-poem/→ random poem/blog/api/info/→ JSON response
If all of these work, you’ve successfully completed Lesson 5: Views with clean, error-free code.

