Django: Company Website
Published:
Bab ini membahas pembuatan proyek Company Website dengan Django 6 pada folder kerja project4, dengan fokus pada pendalaman template, penerapan class-based view, serta pengujian aplikasi yang lebih sistematis.
Pada bab ini kita akan mempelajari:
- Setup proyek keempat pada folder
project4. - Konsep
project-level templates. - Function-based view untuk Homepage.
- Template context, tag, dan filter Django.
- Class-based view (
TemplateView) untuk About page. get_context_data()untuk mengirim context pada CBV.- Template inheritance dengan
base.html. - Named URLs untuk menghindari hardcoded path.
- Pengujian URL, nama URL, template, dan konten.
- Workflow Git dan GitHub untuk menyimpan progres.
1. Gambaran Bab Company Website
Ini adalah proyek keempat sebelum masuk ke proyek berbasis database dan model Django. Karena itu, bab ini berfungsi untuk memperkuat tiga area non-model yang sangat penting:
- Views
- URLs
- Templates
Di chapter asli, setup masih menggunakan seri Django 5. Pada catatan ini, kita sesuaikan seluruh langkah ke Django 6 agar konsisten dengan bab sebelumnya.
2. Setup Awal pada project4
2.1 Membuat folder kerja
# Windows
cd onedrive\desktop\pawf\django
mkdir project4
cd project4
# macOS
cd ~/desktop/pawf/django
mkdir -p project4
cd project4
Pastikan Anda tidak sedang berada di virtual environment lain. Jika masih aktif, jalankan:
deactivate
2.2 Membuat virtual environment dan instal paket
# Windows
python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install Django==6.0.4 black
# macOS
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install Django==6.0.4 black
2.3 Membuat project dan app
django-admin startproject django_project .
python manage.py startapp pages
Daftarkan app pages di django_project/settings.py:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"pages", # new
]
Inisialisasi database dan jalankan server:
python manage.py migrate
python manage.py runserver
Buka http://127.0.0.1:8000/ untuk memastikan halaman awal Django muncul.
3. Project-Level Templates
Pada bab sebelumnya kita menaruh template di tingkat app (mis. pages/templates/pages/). Di bab ini, kita mencoba pendekatan yang juga sangat populer: satu folder templates di tingkat proyek.
Keuntungan pendekatan ini:
- Semua template terkumpul di satu tempat.
- Lebih cepat saat mencari dan memperbarui template.
- Cocok untuk situs kecil-menengah dengan banyak halaman statis.
Hentikan server, lalu buat folder template global:
mkdir templates
Perbarui django_project/settings.py pada konfigurasi TEMPLATES:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"], # new
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
Buat file templates/home.html:
<h1>Company Homepage</h1>
Struktur direktori project4 pada tahap ini (baru homepage):
project4/
├── .venv/
├── db.sqlite3
├── manage.py
├── django_project/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── pages/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ ├── views.py
│ └── migrations/
└── templates/
└── home.html
4. Function-Based View dan URL
Perbarui pages/views.py:
from django.shortcuts import render
def home_page_view(request):
return render(request, "home.html")
Buat pages/urls.py:
from django.urls import path
from .views import home_page_view
urlpatterns = [
path("", home_page_view),
]
Hubungkan ke project URL di django_project/urls.py:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("pages.urls")),
]
Jalankan server:
python manage.py runserver
Buka http://127.0.0.1:8000/ dan halaman Company Homepage akan tampil.
5. Template Context, Tags, dan Filters
Tambahkan context ke homepage pada pages/views.py:
from django.shortcuts import render
def home_page_view(request):
context = {
"inventory_list": ["Widget 1", "Widget 2", "Widget 3"],
"greeting": "THAnk you FOR visitING.",
}
return render(request, "home.html", context)
Perbarui templates/home.html:
<h1>Company Homepage</h1>
<p>The current date and time is: {% now "DATETIME_FORMAT" %}</p>
<p>There are {{ inventory_list|length }} items of inventory.</p>
<ul>
{% for item in inventory_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
<p>{{ greeting|title }}</p>
{% comment %}Add more content here!{% endcomment %}

Yang dipraktikkan pada bagian ini:
context: dictionary key-value dari view ke template.nowtag: menampilkan waktu/tanggal sesuai format Django.lengthfilter: menghitung panjang list/string.fortag: melakukan iterasi item list.titlefilter: ubah teks menjadi title case.commenttag: komentar yang tidak muncul di browser.
6. Function-Based View vs Class-Based View
Di komunitas Django, diskusi FBV vs CBV sangat umum.
Ringkasnya:
- Function-based view (FBV) mudah dipahami untuk pemula.
- FBV bisa menjadi panjang dan repetitif pada proyek besar.
- Class-based view (CBV) lebih reusable berkat inheritance.
- Generic class-based views membantu mengabstraksi pola umum.
Secara historis, Django kini sangat mendorong penggunaan class-based/generic class-based views untuk kasus-kasus yang sesuai karena maintainability lebih baik.
7. About Page dengan TemplateView
Perbarui pages/views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
def home_page_view(request):
context = {
"inventory_list": ["Widget 1", "Widget 2", "Widget 3"],
"greeting": "THAnk you FOR visitING.",
}
return render(request, "home.html", context)
class AboutPageView(TemplateView):
template_name = "about.html"
Perbarui pages/urls.py:
from django.urls import path
from .views import AboutPageView, home_page_view
urlpatterns = [
path("about/", AboutPageView.as_view()),
path("", home_page_view),
]
Catatan penting:
- CBV harus dipanggil dengan
.as_view()saat dipasang ke URL. - Inilah perbedaan paling mendasar pada konfigurasi URL antara FBV dan CBV.
Buat templates/about.html:
<h1>Company About Page</h1>
Buka http://127.0.0.1:8000/about/.

8. get_context_data() pada Class-Based View
Salah satu metode paling penting pada generic CBV adalah get_context_data().
Perbarui class AboutPageView pada pages/views.py:
class AboutPageView(TemplateView):
template_name = "about.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["contact_address"] = "123 Main Street"
context["phone_number"] = "555-555-5555"
return context
Perbarui templates/about.html:
<h1>Company About Page</h1>
<p>
The company address is {{ contact_address }} and the phone number is
{{ phone_number }}.
</p>
Gunakan sintaks variabel Django Template (kurung kurawal ganda) untuk menampilkan nilai context di template.
9. Template Inheritance
Fitur kuat lain dari template Django adalah pewarisan template.
Buat templates/base.html:
<header>
<a href="/">Home</a> |
<a href="/about">About</a>
</header>
{% block content %}{% endblock %}
Perbarui templates/home.html:
{% extends "base.html" %}
{% block content %}
<h1>Company Homepage</h1>
<p>The current date and time is: {% now "DATETIME_FORMAT" %}</p>
<p>There are {{ inventory_list|length }} items of inventory.</p>
<ul>
{% for item in inventory_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
<p>{{ greeting|title }}</p>
{% comment %}Add more content here!{% endcomment %}
{% endblock %}
Perbarui templates/about.html:
{% extends "base.html" %}
{% block content %}
<h1>Company About Page</h1>
<p>
The company address is {{ contact_address }} and the phone number is
{{ phone_number }}.
</p>
{% endblock %}
Dengan pendekatan ini, header cukup ditulis sekali di base.html dan dipakai semua halaman.

10. Named URLs
Hardcoded URL (/, /about) rawan error saat route berubah. Best practice Django adalah memberi nama URL, lalu memanggilnya berdasarkan nama.
Perbarui pages/urls.py:
from django.urls import path
from .views import AboutPageView, home_page_view
urlpatterns = [
path("about/", AboutPageView.as_view(), name="about"),
path("", home_page_view, name="home"),
]
Perbarui templates/base.html:
<header>
<a href="{% url 'home' %}">Home</a> |
<a href="{% url 'about' %}">About</a>
</header>
{% block content %}{% endblock %}
Manfaat named URL:
- Sumber kebenaran route ada di
urls.py. - Template dan kode lain tidak tergantung path hardcoded.
- Refactor URL jadi jauh lebih aman.
Kebutuhan file template pada bab ini:
templates/home.htmltemplates/about.htmltemplates/base.html
Struktur direktori lengkap project4 sebelum masuk bagian testing:
project4/
├── .venv/
├── db.sqlite3
├── manage.py
├── django_project/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── pages/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ ├── views.py
│ └── migrations/
└── templates/
├── about.html
├── base.html
└── home.html
11. Testing (URL, Name, Template, Content)
11.1 Uji dasar status code
Isi awal pages/tests.py:
from django.test import SimpleTestCase
class HomepageTests(SimpleTestCase):
def test_url_exists_at_correct_location(self):
response = self.client.get("/")
self.assertEqual(response.status_code, 200)
class AboutpageTests(SimpleTestCase):
def test_url_exists_at_correct_location(self):
response = self.client.get("/about/")
self.assertEqual(response.status_code, 200)
Jalankan:
python manage.py test
11.2 Uji berdasarkan nama URL (reverse)
Perbarui pages/tests.py:
from django.test import SimpleTestCase
from django.urls import reverse
class HomepageTests(SimpleTestCase):
def test_url_exists_at_correct_location(self):
response = self.client.get("/")
self.assertEqual(response.status_code, 200)
def test_url_available_by_name(self):
response = self.client.get(reverse("home"))
self.assertEqual(response.status_code, 200)
class AboutpageTests(SimpleTestCase):
def test_url_exists_at_correct_location(self):
response = self.client.get("/about/")
self.assertEqual(response.status_code, 200)
def test_url_available_by_name(self):
response = self.client.get(reverse("about"))
self.assertEqual(response.status_code, 200)
11.3 Uji template dan konten
Perbarui pages/tests.py lagi:
from django.test import SimpleTestCase
from django.urls import reverse
class HomepageTests(SimpleTestCase):
def test_url_exists_at_correct_location(self):
response = self.client.get("/")
self.assertEqual(response.status_code, 200)
def test_url_available_by_name(self):
response = self.client.get(reverse("home"))
self.assertEqual(response.status_code, 200)
def test_template_name_correct(self):
response = self.client.get(reverse("home"))
self.assertTemplateUsed(response, "home.html")
def test_template_content(self):
response = self.client.get(reverse("home"))
self.assertContains(response, "<h1>Company Homepage</h1>")
class AboutpageTests(SimpleTestCase):
def test_url_exists_at_correct_location(self):
response = self.client.get("/about/")
self.assertEqual(response.status_code, 200)
def test_url_available_by_name(self):
response = self.client.get(reverse("about"))
self.assertEqual(response.status_code, 200)
def test_template_name_correct(self):
response = self.client.get(reverse("about"))
self.assertTemplateUsed(response, "about.html")
def test_template_content(self):
response = self.client.get(reverse("about"))
self.assertContains(response, "<h1>Company About Page</h1>")
Saat dijalankan, total test akan berkembang dari 2 test menjadi 4 test lalu 8 test.
12. Git dan GitHub
Inisialisasi dan cek status:
git init
git status
Melakukan Commit:
git add .
git commit -am "Add project company website with views, urls, templates, and tests"
Hubungkan ke GitHub dan push:
git remote add origin https://github.com/<username>/company-website.git
git branch -M main
git push -u origin main
13. Ringkasan
Pada bab Company Website ini, kita telah membangun implementasi lengkap Django 6 pada struktur kerja project4, meliputi:
- project-level templates,
- function-based + class-based view,
get_context_data()pada CBV,- template inheritance,
- named URLs,
- pengujian yang lebih lengkap,
- dan workflow Git/GitHub.
Bab berikutnya akan menjadi titik penting karena kita mulai masuk ke proyek Django berbasis database (models), yaitu saat kekuatan utama Django mulai terasa secara penuh.
Referensi
Django for Beginners by William S. Vincent



