Belajar Django - URL Routing & Views
Episode 4 of 27

Belajar Django - URL Routing & Views

Menulis URLconf dengan urlpatterns dan path converters, memahami name- based reverse agar URL tidak di-hardcode, membandingkan Function-Based Views (FBV) dengan Class-Based Views (CBV), serta memakai HttpResponse dan JsonResponse untuk respons pertama.

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Setelah project devblog berdiri di episode 3, sekarang kita mengisi dua lapisan pertama siklus request dari episode 2: URLconf dan Views. Di episode ini kalian menulis URL pertama, menangkap parameter dari path, dan menulis view yang mengembalikan HTML maupun JSON.

Mengapa topik ini penting? URL adalah kontrak antara aplikasi kalian dan dunia luar. Begitu sebuah URL dipakai pengguna, crawler, atau API client, mengubahnya seenaknya akan memutus banyak hal. Karena itu Django menyediakan sistem name-based reverse: kalian merujuk URL lewat nama, bukan string, sehingga URL bisa diubah kapan saja tanpa memutus kode lain.

URLconf: urlpatterns dan path

URLconf adalah daftar pola yang memetakan URL ke view. Di devblog/urls.py (root), semua route project di-include per app:

Pythondevblog/urls.py
from django.contrib import admin
from django.urls import include, path
 
urlpatterns = [
    path("admin/", admin.site.urls),
    path("", include("blog.urls")),
]

include("blog.urls") menyerahkan penanganan path yang dimulai dengan "" ke file blog/urls.py. Sekarang buat file itu:

Pythonblog/urls.py
from django.urls import path
 
from . import views
 
urlpatterns = [
    path("", views.home, name="home"),
    path("posts/<int:pk>/", views.post_detail, name="post_detail"),
    path("posts/<slug:slug>/", views.post_detail_by_slug, name="post_by_slug"),
]

Perhatikan pola posts/<int:pk>/ dan posts/<slug:slug>/: <int:pk> adalah path converter yang hanya menerima integer dan meneruskannya sebagai parameter bernama pk. Converter bawaan Django:

ConverterMenerimaContoh
strstring tanpa / (default)hello
intbilangan bulat positif42
slughuruf, angka, -, _belajar-django
uuidUUID v4550e8400-e29b-...
pathstring apa pun termasuk /dir/file.txt

Tip

Jangan pernah memakai converter str longgar seperti posts/<pk>/ tanpa batasan jika parameter dipakai untuk query database — nanti pk bisa berupa string apa pun. Gunakan int atau slug sesuai domain data kalian; ini sekaligus mencegah request tak valid masuk jauh ke sistem.

Function-Based Views adalah cara paling lurus: fungsi Python yang menerima request dan mengembalikan respons.

Pythonblog/views.py - FBV
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, get_object_or_404
 
from .models import Post
 
def home(request):
    posts = Post.objects.filter(published=True)
    return render(request, "blog/post_list.html", {"posts": posts})
 
def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, "blog/post_detail.html", {"post": post})

render() merender template dengan konteks. get_object_or_404 menggabungkan query dan 404 handling: jika objek tidak ditemukan, otomatis melempar Http404 — mencegah error DoesNotExist mentah yang bocor ke user.

Untuk respons non-HTML, gunakan JsonResponse:

Pythonblog/views.py - JsonResponse
from django.http import JsonResponse
 
def healthz(request):
    return JsonResponse({"status": "ok", "version": 1})

JsonResponse mengubah dict menjadi JSON, mengatur header Content-Type: application/json, dan — penting — hanya menerima data JSON-serializable. Ini menjadi dasar REST API yang akan kita bangun penuh di episode 11.

Class-Based Views (CBV)

Ketika logika view bertambah, FBV berisiko jadi panjang dan berulang. Django menyediakan Class-Based Views: view sebagai class yang logikanya dipecah ke method bernama.

Pythonblog/views.py - CBV
from django.views.generic import ListView, DetailView
 
from .models import Post
 
class PostListView(ListView):
    model = Post
    template_name = "blog/post_list.html"
    context_object_name = "posts"
    queryset = Post.objects.filter(published=True)
 
class PostDetailView(DetailView):
    model = Post
    template_name = "blog/post_detail.html"

ListView dan DetailView mengatur query, pagination, dan konvensi konteks untuk kalian. context_object_name mengganti nama variabel default (post_listposts). Bandingkan ringkasnya dengan FBV di atas — untuk pola CRUD standar, CBV jelas lebih hemat baris.

AspekFBVCBV
KejelasanLurus, mudah dibaca baris per barisLogika tersebar di method (get, post, get_queryset)
ReusePerlu decorator/fungsi helperInheritance + mixin sangat mudah
EkstensibilitasFungsi dengan argsOverride method per-request
Cocok untukView sederhana & customPola CRUD yang repetitif

Note

Tidak ada pemenang mutlak antara FBV dan CBV — project nyata memakai keduanya. Aturan praktis: gunakan FBV untuk view sederhana dengan logika unik, CBV untuk pola list/detail/form yang berulang. Perbandingan lebih dalam kita bahas saat menulis form di episode 9.

Name-Based Reverse

Perhatikan name="post_detail" di blog/urls.py. Kini semua kode merujuk URL lewat nama, bukan string:

PythonReverse dari dalam kode
from django.urls import reverse
 
reverse("post_detail", args=[42])          # "/posts/42/"
reverse("post_by_slug", kwargs={"slug": "hello"})  # "/posts/hello/"

Dan di dalam template, memakai tag {% url %}:

PythonReverse dari dalam template
<a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a>

Manfaatnya: jika besok kalian mengubah posts/<int:pk>/ menjadi artikel/<int:pk>/, cukup ubah satu baris di urls.py — semua link, redirect, dan form tetap bekerja. Hardcode URL ("/posts/" + str(pk)) adalah salah satu dosa paling umum yang baru terasa saat restrukturisasi.

PythonContoh reverse dengan namespace
# blog/urls.py
app_name = "blog"
 
urlpatterns = [
    path("", views.home, name="home"),
    path("posts/<int:pk>/", views.post_detail, name="post_detail"),
]

Dengan app_name = "blog", template memakai {% url 'blog:post_detail' post.pk %}. Namespace ini penting ketika banyak app punya nama view yang sama (home ada di app A dan app B) — namespace mencegah ambigu.

Uji Coba

Jalankan server dan uji:

Uji route dan reverse
python manage.py runserver
curl -I http://127.0.0.1:8000/healthz/
curl -I http://127.0.0.1:8000/posts/999/

curl -I menampilkan hanya header: endpoint /healthz/ harus mengembalikan 200, sementara /posts/999/ (objek belum ada) mengembalikan 404. Seluruh perilaku HTTP ini adalah kontrak yang akan kalian andalkan saat menulis test di episode 15 dan API di episode 11.

Penutup

Inti yang harus dibawa pulang:

  • urlpatterns memetakan URL ke view; converter int/slug/uuid menyaring parameter.
  • include() menghubungkan URLconf root ke URLconf per-app; app_name memberi namespace.
  • FBV cocok untuk logika unik, CBV (ListView/DetailView) untuk pola CRUD berulang.
  • get_object_or_404 dan JsonResponse menangani 404 dan JSON secara idiomatis.
  • Selalu pakai name-based reverse (reverse/{% url %}), jangan hardcode URL.

Di episode 5 selanjutnya kita masuk ke lapisan presentasi: Templates & Template Language — sintaks DTL, template inheritance dengan base.html, custom filters/tags, dan context processors untuk layout + partials yang bisa dipakai ulang. Sampai jumpa di episode 5!

Belajar Django - URL Routing & Views | Belajar Django