Webmaster and More

Smart WordPress & AI-Powered Solutions for Your Business

Lesson 5: Views – Returning HTML, JSON & Random Poems

In this lesson we’ll make Django think and respond:

We’ll use your existing project:

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:

  1. Receives a request (request)
  2. 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:


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 import render (and redirect) from django.shortcuts at 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 write views.go_to_about but your function is named go_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 in views.py exactly.


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:

🧠 Common mistake #3 – Redirect fails
If you see NameError: '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:

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 says views.poem_detail but you never created the function.
✅ Always create the view function before wiring it in urls.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 only
blog/poems/<int:id>/ but not blog/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:

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

✔ URLs and Views Match

✔ Paths You Can Visit

If all of these work, you’ve successfully completed Lesson 5: Views with clean, error-free code.