Chapter 1: Django Home
Home part of a Django project — the landing page / homepage / welcome screen that users see first when they visit your domain (like example.com/ or 127.0.0.1:8000/).
Many beginners get confused here because the official poll tutorial doesn’t create a nice homepage — it just jumps straight to /polls/. In real projects we almost always want something prettier and more meaningful at the root URL.
I’ll explain this like we’re pair-programming together — slowly, with reasoning, common mistakes, modern 2025–2026 best practices, and several realistic ways people actually do it today.
Quick reality check — what most real projects do in 2025/2026
| Style | When people use it | Pros | Cons | Folder name people choose |
|---|---|---|---|---|
| No separate app | Very small / micro projects, prototypes | Zero extra files | Messy urls.py later | — |
| pages / core app | Most medium projects (very popular) | Clean, conventional | One more app | pages or core |
| home app | Some teams like explicit names | Very clear intent | Slightly non-standard | home |
| Just TemplateView in project urls.py | Landing page = marketing / static-ish page | Fastest possible | Harder to grow later | — |
| landing + marketing tools | SaaS startups with hero sections, waitlists | Full control over sections | Overkill for internal tools | landing |
Most common & recommended today → create small app called pages or core and put homepage there.
Option 1 – Recommended: Small pages app (clean & scalable)
We continue from your previous project folder (mypolls/ with mysite/ + polls/).
|
0 1 2 3 4 5 6 7 |
# still inside virtualenv python manage.py startapp pages |
Add it to INSTALLED_APPS in mysite/settings.py (near ‘polls.apps.PollsConfig’):
|
0 1 2 3 4 5 6 7 8 9 10 |
INSTALLED_APPS = [ ... 'polls.apps.PollsConfig', 'pages.apps.PagesConfig', # ← add this ] |
Create basic structure inside pages/
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pages/ ├── __init__.py ├── admin.py ├── apps.py ├── migrations/ ├── models.py # ← usually empty for home ├── tests.py ├── urls.py # ← we create this now └── views.py |
pages/views.py
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
from django.shortcuts import render from django.views.generic import TemplateView # Option A: function-based view (simple & very common) def home(request): context = { "title": "Welcome to My Polls App", "message": "Create amazing polls and see what people really think!", "show_polls_link": True, # you can make logic here later } return render(request, "pages/home.html", context) # Option B: class-based (very clean when you want to reuse / extend later) class HomeView(TemplateView): template_name = "pages/home.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["title"] = "My Awesome Polling Platform" context["current_year"] = 2026 context["featured_message"] = "Vote wisely!" return context |
Many teams prefer function-based for the absolute simplest homepage — it’s easier to read when you’re learning.
Create pages/urls.py
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
from django.urls import path # from .views import home # function-based from .views import HomeView # class-based (I’ll use this now) urlpatterns = [ # path('', home, name='home'), # function version path('', HomeView.as_view(), name='home'), ] |
Connect it in the project mysite/urls.py
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('polls/', include('polls.urls')), path('', include('pages.urls')), # ← root URL → pages app ] |
Important: put path(”) last — Django reads top-to-bottom. If you put it first, everything else would never match.
Now the template — pages/templates/pages/home.html
First create folders:
|
0 1 2 3 4 5 6 |
mkdir -p pages/templates/pages |
pages/templates/pages/home.html
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ title|default:"My Polls" }}</title> <style> body { font-family: system-ui, sans-serif; max-width: 800px; margin: 4rem auto; text-align: center; } h1 { color: #2563eb; } .btn { display: inline-block; padding: 0.8rem 1.6rem; background: #2563eb; color: white; text-decoration: none; border-radius: 6px; font-weight: 500; } .btn:hover { background: #1d4ed8; } </style> </head> <body> <h1>{{ title }}</h1> <p style="font-size: 1.3rem; color: #4b5563;"> {{ message|default:"This is the future home of great polls." }} </p> {% if show_polls_link %} <p> <a href="{% url 'polls:index' %}" class="btn">See all available polls →</a> </p> {% endif %} <footer style="margin-top: 4rem; color: #9ca3af; font-size: 0.9rem;"> © {{ current_year }} — Built with Django 6.0 • Hyderabad, India </footer> </body> </html> |
Run server:
|
0 1 2 3 4 5 6 |
python manage.py runserver |
Go to http://127.0.0.1:8000/ → you should see nice welcome page!
Option 2 – Even simpler (no extra app – good for tiny projects)
In mysite/urls.py:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), path('polls/', include('polls.urls')), path('', TemplateView.as_view(template_name='home.html'), name='home'), ] |
Then create templates/home.html (in project-level templates/ folder — you need to add ‘DIRS’: [BASE_DIR / ‘templates’], to TEMPLATES setting).
This is fast but becomes messy when you want:
- context processors
- different logic for logged-in users
- hero image / stats / testimonials
So most people move to pages app after first weekend.
Option 3 – Very modern minimal landing page (2026 style – Tailwind or Pico CSS)
Many developers now use CDN-based minimal CSS frameworks.
Example with Pico CSS (very light, no build step):
In <head> add:
|
0 1 2 3 4 5 6 |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"> |
Then body becomes:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<main class="container"> <h1>Welcome to VoteSphere</h1> <p>Real-time polls. Honest opinions. Zero drama.</p> <article> <hgroup> <h2>Ready to ask something?</h2> <h3>Join 12,400+ users already voting</h3> </hgroup> <a href="{% url 'polls:index' %}" role="button" class="contrast">Browse Polls</a> <a href="#" role="button">Create Account</a> </article> </main> |
Looks surprisingly professional with almost zero effort.
Quick checklist – did I miss anything important?
- Template folder structure → pages/templates/pages/ (namespaced) prevents name clashes later
- Use {% url ‘polls:index’ %} — never hardcode /polls/
- Add name=’home’ → you can use {% url ‘home’ %} in future navbars
- Consider adding robots.txt, favicon.ico later in the same pages app
Which style should YOU choose right now?
- Just learning → Option 1 with pages app + function-based view (most readable, teaches app structure correctly)
- Want fastest result → Option 2 with TemplateView
- Building real product → Option 1 + add Tailwind/Pico/Bulma via CDN
Try creating the pages version now — it usually takes 8–12 minutes.
Once done, come back and tell me:
- Did it work?
- Want to add login/logout links?
- Want nice navbar that appears on all pages?
- Or continue to polls detail + voting page?
I’m right here 😄
