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:
django-admin startproject toko .
python3 manage.py startapp katalog
python3 manage.py checkOutput yang Dihasilkan:
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:
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.pyPembagian 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:
| Peran | Django (MTV) | Framework lain (MVC) |
|---|---|---|
| Mengelola data dan logika bisnis | Model (models.py) | Model |
| Menampilkan halaman | Template (templates/) | View |
| Menerima request dan memilih respons | View (views.py) | Controller |
| Memetakan URL ke handler | URLconf (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:
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:
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:
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:
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 = 404Saat 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:
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:
| Pengaturan | Isi bawaan | Perannya |
|---|---|---|
BASE_DIR | Path(__file__).resolve().parent.parent | titik nol path proyek |
SECRET_KEY | string acak | kunci tanda tangan session dan CSRF |
DEBUG | True | menampilkan 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.