Django URLs and Views Explained There was a point in my Django journey where I could create a project, create an app, define a model, and register it in the admin — but if you’d asked me how a URL actually turns into a visible webpage, I would have just shrugged. I was following steps without understanding the connection between them. Once I finally understood URLs and Views, a lot of the earlier pieces clicked into place too.
So this post is about that missing link — how typing an address into a browser ends up showing content on screen.
Table of Contents
The Short Version First (Django URLs and Views Explained)
When someone visits a page on your Django site, two files work together to decide what they see: urls.py figures out which piece of code should handle the request, and views.py contains that code, deciding what actually gets shown. If you’ve read my earlier post on the Django project structure, you’ve already met both of these files — now let’s see them actually work together.
Starting With urls.py
Every request that hits your Django site passes through urls.py first. Think of it as a receptionist — it doesn’t do the actual work, it just looks at the address you typed and points you to the right department.
A basic urls.py might look like this:
python
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('about/', views.about, name='about'),
]
Each path() here connects a URL pattern to a specific function inside views.py. Visit /about/, and Django checks this list, finds a match, and calls the about function to handle it.
Now, views.py
Once urls.py decides which function should run, that function lives in views.py. This is where the actual logic happens — deciding what data to fetch, what to calculate, and what to send back to the browser.
A simple view looks like this:
python
from django.http import HttpResponse
def home(request):
return HttpResponse("Welcome to my site!")
That’s genuinely all a view needs to be — a Python function that takes a request and returns a response. It can be that simple, or much more complex, depending on what the page needs to do.
Connecting a View to a Database
Views get more useful once they start pulling real data. Here’s a view that fetches blog posts and passes them to an HTML template instead of just returning plain text:
python
from django.shortcuts import render
from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})
This is where models.py, which I covered in my post on the Django app structure, connects into the picture. The view asks the model for data, then hands that data off to a template to be displayed.
The Full Journey of a Single Request
I find it helps to walk through this step by step, because it removes the mystery:
- You visit
yoursite.com/blog/ - Django’s main
urls.pychecks the incoming path - It matches
/blog/and routes the request to theblogapp’s ownurls.py - That file matches the request to a specific view function
- The view runs, maybe pulling data from
models.py - The view returns a response — either plain text, JSON, or a rendered HTML page
- Your browser receives that response and displays it
Every page load on a Django site follows this exact chain. Once I actually traced through it manually a few times, debugging broken pages became dramatically easier.
Project-Level urls.py vs App-Level urls.py
One thing that confused me early on: most tutorials show two separate urls.py files. The project-level one, sitting next to settings.py, usually just delegates to each app:
python
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls')),
]
Then inside the blog app, its own urls.py handles everything specific to blog pages. This keeps routing organized as your site grows — instead of one massive list of URLs, each app manages its own small piece.
Naming Your URLs
You’ll notice the name='home' part in the path() examples above. I ignored this for a while, but it’s genuinely useful. Instead of hardcoding /about/ everywhere in your templates, you can reference the URL by name:
html
<a href="{% url 'about' %}">About</a>
If you ever change the actual URL path later, you only update it in one place, and every link using that name updates automatically. Small habit, saves real headaches later.
Common Mistakes I Made Early On
- Forgetting to
include()the app’surls.pyin the project-level file, so nothing loaded - Mismatching the view function name between
urls.pyandviews.py - Returning nothing from a view function, which throws an error instead of a blank page
- Not adding a trailing slash consistently, which occasionally caused unexpected 404s
None of these are complicated once you know to look for them, but they cost me real debugging time before I did.
Wrapping the Series Together
At this point, if you’ve followed along from the start, you’ve seen the full loop: the project sets up the outer structure, an app holds a specific feature, models.py defines the data, and now urls.py and views.py connect a browser request to that data and back. That’s genuinely the entire request-response cycle in Django, just spread across a few clearly separated files.
For deeper reference beyond what I’ve covered here, the official Django documentation on URL dispatching is worth reading once this basic picture makes sense to you.
Final Thoughts
Understanding URLs and Views was the point where Django stopped feeling like a set of commands to memorize and started feeling like a system I actually understood. Try tracing one request through your own project right now — from the browser, through urls.py, into views.py, and back. It’s the fastest way to make this stick.
Django URLs සහ Views සිංහලෙන් පැහැදිලි කිරීමක්
මම Django ඉගෙන ගන්න කාලේ, project එකක් හදලා, app එකක් හදලා, model එකක් හදලා, ඒක admin panel එකට add කරන්න පුළුවන් වුණත්, “URL එකක් type කරාම page එක load වෙන්නේ කොහොමද” කියලා අහුවුනොත් මට හරියටම උත්තර දෙන්න බැරි වුණා. Steps follow කරනවා විතරක් නෙවෙයි, ඒවා අතරේ connection එක තේරෙන්නත් ඕන කියලා පස්සේ තමයි තේරුනේ.
ඒ නිසා අද මේ පෝස්ට් එකෙන් කතා කරන්නේ ඒ missing link එක ගැන – browser එකට URL එකක් type කරාම, screen එකේ content එකක් පේන්නේ කොහොමද කියලා.
කෙටියෙන් කිව්වොත්
කවුරුහරි ඔයාගේ Django site එකේ page එකකට visit කරාම, files දෙකක් එකට වැඩ කරනවා: urls.py file එක තීරණය කරනවා ඒ request එක කුමන code එක handle කරන්නද කියලා, views.py file එකේ තියෙනවා ඒ code එක, actually screen එකේ පෙන්නන්නේ මොකක්ද කියලා තීරණය කරන එක. Django project structure ගැන මගේ කලින් post එකේ මේ files දෙකම ඔයාට හම්බුනා ඇති, දැන් බලමු ඒවා එකට වැඩ කරන්නේ කොහොමද කියලා.
urls.py එකෙන් පටන් ගමු
ඔයාගේ Django site එකට එන හැම request එකක්ම මුලින්ම යන්නේ urls.py file එකට. මට ඒක හිතෙන්නේ receptionist කෙනෙක් වගේ – actual වැඩේ කරන්නේ නෑ, ඔයා type කරපු address එක බලලා, හරි department එකට point කරනවා විතරයි.
සරලම urls.py file එකක් මෙහෙම පේනවා:
python
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('about/', views.about, name='about'),
]
මෙතන ඉන්න path() එකින් එක URL pattern එකක් views.py file එකේ තියෙන function එකකට connect කරනවා. /about/ එකට visit කරාම, Django මේ list එක check කරලා, match එකක් හොයාගෙන, about function එක call කරනවා.
දැන් views.py
urls.py එකෙන් කුමන function එක run කරන්නද කියලා තීරණය කරාට පස්සේ, ඒ function එක තියෙන්නේ views.py file එකේ. Actual logic එක වෙන්නේ මෙතනයි – මොන data එකක්ද ගන්නේ, මොකක්ද calculate කරන්නේ, browser එකට ආපහු මොකක්ද යවන්නේ කියලා තීරණය කරන තැන.
සරල view එකක් මෙහෙම පේනවා:
python
from django.http import HttpResponse
def home(request):
return HttpResponse("Welcome to my site!")
View එකකට ඕන වෙන්නේ ඇත්තටම මේ විතරයි – request එකක් ගන්නා, response එකක් return කරන Python function එකක්. මේ තරම් simple වෙන්නත් පුළුවන්, page එකට අවශ්ය දේ අනුව ගොඩක් complex වෙන්නත් පුළුවන්.
Database එකට View එකක් Connect කිරීම
Views actual data ගන්න පටන් ගත්තට පස්සේ තමයි ඒවා useful වෙන්නේ. මේ view එකෙන් blog posts ටිකක් ගෙනල්ල, plain text return කරනවා වෙනුවට, HTML template එකකට pass කරනවා:
python
from django.shortcuts import render
from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})
Django app structure ගැන මගේ post එකේ discuss කරපු models.py file එක connect වෙන්නේ මෙතනයි. View එක model එකෙන් data ඉල්ලනවා, ඊට පස්සේ ඒ data එක template එකට දීලා display කරනවා.
එක Request එකක සම්පූර්ණ Journey එක
මේක step by step කියවීම ගොඩක් උදව් වෙනවා, මොකද ඒකෙන් confusion එක අයින් වෙනවා:
- ඔයා
yoursite.com/blog/එකට visit කරනවා - Django ගේ main
urls.pyඑක එන path එක check කරනවා /blog/එක match වෙලා, request එකblogapp එකේ ownurls.pyඑකට route වෙනවා- ඒ file එක specific view function එකකට request එක match කරනවා
- View එක run වෙනවා, සමහර වෙලාවට
models.pyඑකෙන් data ගන්නවා - View එක response එකක් return කරනවා – plain text, JSON, හෝ rendered HTML page එකක්
- ඔයාගේ browser එකට ඒ response එක ලැබිලා, ඒක display කරනවා
Django site එකක හැම page load එකක්ම යන්නේ මේ exact chain එකෙන්මයි. මම මේක manually ටිකක් trace කරලා බැලුවට පස්සේ, break වෙච්ච pages debug කරන එක ගොඩක් පහසු වුණා.
Project-Level urls.py vs App-Level urls.py
මුලින් මාව confuse කරපු දෙයක් තමයි – tutorials ගොඩක් urls.py files දෙකක් පෙන්නනවා. settings.py එක ළඟ තියෙන project-level එක, සාමාන්යයෙන් හැම app එකකටම delegate කරනවා:
python
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls')),
]
ඊට පස්සේ blog app එක ඇතුළේ, ඒකේම urls.py එක blog pages වලට specific හැම දේම handle කරනවා. Site එක growing වෙනකොට මේකෙන් routing එක organized විදිහට තියාගන්න පුළුවන් – URLs ලොකු list එකක් වෙනුවට, එක එක app එක ඒකේම කොටස manage කරනවා.
URLs වලට නම් දාන එක
ඉහත path() examples වල name='home' කියන කොටස ඔයා දැක ඇති. මම මුලදී මේක ignore කළා, ඒත් ඇත්තටම useful දෙයක්. Templates ඔක්කොටම /about/ කියලා hardcode කරනවා වෙනුවට, URL එක name එකෙන් reference කරන්න පුළුවන්:
html
<a href="{% url 'about' %}">About</a>
පස්සේ actual URL path එක change කරන්න ඕන වුණොත්, එක තැනක update කරාම ඇති, ඒ name එක use කරන හැම link එකක්ම automatically update වෙනවා. කුඩා habit එකක්, ඒත් පස්සේ real headache save කරනවා.
මම මුලදී කරපු Common Mistakes
- App එකේ
urls.pyඑක project-level file එකටinclude()කරන්න අමතක වීම, ඒකෙන් කිසිම දෙයක් load නොවීම urls.pyසහviews.pyඅතර view function එකේ නම mismatch වීම- View function එකකින් කිසිම දෙයක් return නොකිරීම, ඒකෙන් blank page එකක් වෙනුවට error එකක් throw වීම
- Trailing slash එක consistent විදිහට add නොකිරීම, ඒකෙන් සමහර වෙලාවට unexpected 404 errors ඒම
මේවා කිසිම complex දෙයක් නෙවෙයි, ඒත් ඒවා හොයාගන්න මට real debugging time ගියා.
Series එක එකට Wrap කිරීම
ඔයා මුල ඉඳන් follow කළා නම්, දැන් ඔයාට Django request-response cycle එකේ full loop එක පේනවා: project එක outer structure එක setup කරනවා, app එකක් specific feature එකක් තියාගෙන ඉන්නවා, models.py data එක define කරනවා, දැන් urls.py සහ views.py browser request එකක් ඒ data එකට connect කරලා ආපහු එයි. ඒක තමයි Django එකේ request-response cycle එක සම්පූර්ණයෙන්ම, files ටිකක් clear විදිහට separate කරලා විතරයි.
මෙතන cover කරපු දේට වඩා deep reference එකක් ඕන නම්, official Django documentation on URL dispatching එක කියවන එක worth කරනවා, මේ basic picture එක තේරුනට පස්සේ.
අවසාන
URLs සහ Views තේරුම් ගත්ත moment එකෙන් තමයි Django මට memorize කරන්න ඕන commands set එකක් වගේ feel වීම නවත්තලා, මම ඇත්තටම තේරුම් ගත්ත system එකක් වගේ feel වෙන්න පටන් ගත්තේ. දැන්ම ඔයාගේම project එකේ එක request එකක් trace කරලා බලන්න – browser එකේ ඉඳන්, urls.py හරහා, views.py එකට ගිහින්, ආපහු එනකම්. මේක stick කරගන්න තියෙන fastest way එක ඒකයි.

One thought on “Django URLs and Views Explained: How a Web Page Actually Loads”