Flask memberi kita kebebasan memilih sendiri database, library form, dan struktur proyek. Django mengambil jalan sebaliknya: semua kebutuhan aplikasi web — ORM, migrasi, admin, autentikasi, session, form — sudah tersedia di dalam paket dan siap dipakai. Filosofi ini dijuluki batteries included. Versi yang dipakai di lingkungan uji kita adalah Django 6.1.2, dan seluruh perintah pada chapter ini dijalankan sungguhan pada versi tersebut.

Membuat Proyek: startproject dan startapp #

Django menyediakan perintah untuk membuat kerangka proyek, bukan mengetiknya manual. Dari direktori kerja kosong, jalankan:

bash
django-admin startproject toko .
python3 manage.py startapp katalog
python3 manage.py check

Output yang Dihasilkan:

text
System check identified no issues (0 silenced).

Perintah pertama membuat proyek bernama toko (tanda titik membuat berkas langsung di direktori ini, tanpa folder tambahan), perintah kedua membuat aplikasi bernama katalog di dalam proyek, dan check memverifikasi semuanya konsisten. Hasilnya berupa struktur standar:

text
toko/
├── manage.py
├── katalog/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations/
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── toko/
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Pembagian perannya jelas: direktori toko/ berisi konfigurasi proyek, sedangkan katalog/ berisi kode fitur. Perbedaan proyek dan aplikasi disengaja — satu proyek boleh berisi banyak aplikasi, dan aplikasi boleh dipakai ulang antar proyek. Konvensi Django: aplikasi berisi satu domain fitur (katalog, pembayaran, laporan).

MTV: Model, Template, View #

Django menyebut arsitekturnya MTV. Istilahnya mirip MVC yang dikenal di framework lain, hanya namanya bergeser:

PeranDjango (MTV)Framework lain (MVC)
Mengelola data dan logika bisnisModel (models.py)Model
Menampilkan halamanTemplate (templates/)View
Menerima request dan memilih responsView (views.py)Controller
Memetakan URL ke handlerURLconf (urls.py)Routing

Yang paling sering mengejutkan pemula: view di Django bukan template — view adalah fungsi Python yang menerima request dan mengembalikan response, seperti handler pada Flask.

View dan URLconf Pertama #

Isi katalog/views.py — dua view sederhana:

python
from django.http import HttpResponse


def beranda(request):
    html = "<h1>Toko Buku Online</h1><p>Selamat datang di toko kami.</p>"
    return HttpResponse(html)


def tentang(request):
    return HttpResponse("Halaman tentang toko.")

Setiap view menerima satu argument request berisi data permintaan. Selanjutnya toko/urls.py memetakan URL ke view tersebut — berkas inilah yang disebut URLconf:

python
from django.contrib import admin
from django.urls import path

from katalog import views

urlpatterns = [
    path('', views.beranda, name='beranda'),
    path('tentang/', views.tentang, name='tentang'),
    path('admin/', admin.site.urls),
]

Fungsi path() menerima tiga bagian: pola URL, view tujuan, dan nama rute untuk dipakai reverse() — padanan url_for() di Flask. Agar Django mengenali aplikasi katalog, tambahkan 'katalog' di awal list INSTALLED_APPS pada toko/settings.py.

Untuk mengetes tanpa membuka server, kita pakai Client bawaan django.test. Client mengirim header Host: testserver, jadi skrip mandiri seperti ini perlu mendaftarkan host tersebut:

python
import os
import sys

sys.path.insert(0, "django_07")  # sesuaikan: direktori tempat manage.py berada
os.environ["DJANGO_SETTINGS_MODULE"] = "toko.settings"

import django

django.setup()

from django.conf import settings

settings.ALLOWED_HOSTS.append("testserver")

from django.test import Client

client = Client()

r1 = client.get("/")
print("r1.status_code =", r1.status_code)
print("r1.content =", r1.content.decode("utf-8"))

r2 = client.get("/tentang/")
print("r2.status_code =", r2.status_code)
print("r2.text =", r2.text)

r3 = client.get("/tidak-ada/")
print("r3.status_code =", r3.status_code)

Output yang Dihasilkan:

text
r1.status_code = 200
r1.content = <h1>Toko Buku Online</h1><p>Selamat datang di toko kami.</p>
r2.status_code = 200
r2.text = Halaman tentang toko.
r3.status_code = 404

Saat dijalankan dari luar runner test resmi, Django juga mencatat log Not Found: /tidak-ada/ untuk request yang gagal. Di dalam pytest atau test runner Django, penambahan testserver ke ALLOWED_HOSTS dilakukan otomatis — detail ini akan berguna lagi pada Section Testing dan Code Quality.

Menjalankan server pengembangan memakai python3 manage.py runserver. Pada eksekusi nyata dengan port 8005, awal keluarannya:

text
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
October 12, 2026 - 22:02:25
Django version 6.1.2, using settings 'toko.settings'
Starting WSGI development server at http://127.0.0.1:8005/
Quit the server with CONTROL-C.

Baris tanggal mencantumkan waktu server dijalankan sehingga nilainya berubah setiap eksekusi. Perhatikan kalimat Starting WSGI development server — Django sendiri mengakui bahwa runserver adalah server WSGI untuk pengembangan, bukan produksi.

Settings yang Perlu Diketahui #

toko/settings.py hasil startproject sudah berisi konfigurasi yang berfungsi. Empat bagian paling penting bagi pemula:

PengaturanIsi bawaanPerannya
BASE_DIRPath(__file__).resolve().parent.parenttitik nol path proyek
SECRET_KEYstring acakkunci tanda tangan session dan CSRF
DEBUGTruemenampilkan halaman error detail
ALLOWED_HOSTS[]daftar domain yang boleh melayani request

Dua berkas asgi.py dan wsgi.py pada struktur proyek adalah titik masuk kontrak WSGI dan ASGI dari chapter Pengenalan WSGI dan ASGI — Django mendukung keduanya sekaligus.

Admin: Contoh Battery yang Terkenal #

List INSTALLED_APPS bawaan sudah memuat django.contrib.admin — antarmuka pengelolaan data siap pakai di URL /admin/ yang dibuat otomatis. Setelah model Produk kita buat pada chapter berikutnya, admin bisa menampilkan form tambah-ubah-hapus tanpa satu baris kode HTML. Bandingkan dengan Flask yang menuntut extension terpisah untuk fitur serupa, dan posisi Django sebagai framework lengkap mulai terasa masuk akal.