Programming

Tutorial Django untuk Pemula - Membuat Web App Pertama

Pertama kali coba Django, saya langsung kaget betapa cepatnya bisa bikin web app yang jalan. Dalam hitungan jam, dari nol sampai ada CRUD lengkap dengan admin panel. Kalau kamu udah kenal Python tapi belum pernah nyoba web framework-nya, Django itu jawaban paling solid. Framework ini dipercaya oleh Instagram, Pinterest, dan Mozilla - jadi soal skala, nggak perlu diragukan lagi.

Tutorial ini bakal nuntun kamu dari install Django sampai bikin aplikasi To-Do List yang fungsional. Kita bakal bahas setup project, bikin model, view, template, dan cara menjalankan semuanya. Semua code di sini udah dicoba di Python 3.12 dan Django 5.1.

Kenapa Pilih Django?

Sebelum masuk ke code, penting buat ngerti kenapa Django jadi pilihan banyak developer. Django itu "batteries-included" - artinya udah include banyak fitur yang biasanya harus kamu install terpisah di framework lain.

  • ORM (Object-Relational Mapping) - Nggak perlu nulis SQL manual, cukup pakai Python class buat define database
  • Admin Panel - Dashboard admin otomatis dari model yang kamu buat
  • Authentication - Login, register, password reset udah built-in
  • Security - CSRF protection, SQL injection prevention, XSS protection otomatis
  • Scalable - Dipakai Instagram yang handle miliaran request per hari

Dibanding framework Python lain kayak Flask atau FastAPI, Django lebih cocok buat project yang butuh banyak fitur standar. Flask itu minimalis (kamu nambah sendiri yang kamu butuh), sedangkan Django langsung kasih semua. Kalau Flask itu seperti beli tanah kosong, Django itu udah ada fondasi dan dindingnya - tinggal dekorasi.

Install Django dan Setup Project

Langkah pertama tentu saja install Django. Pastikan kamu udah punya Python 3.8+ terinstall. Kalau belum, baca dulu tutorial tentang Python Virtual Environment supaya project kamu rapi.

# Buat virtual environment
python3 -m venv django-env

# Aktifkan virtual environment
# Linux/Mac:
source django-env/bin/activate
# Windows:
django-env\Scripts\activate

# Install Django
pip install django

# Cek versi Django yang terinstall
python -m django --version

Kalau outputnya sesuatu seperti 5.1.4, berarti install berhasil. Sekarang bikin project baru:

# Buat project Django baru
django-admin startproject todoproject

# Masuk ke folder project
cd todoproject

# Lihat struktur project
ls -la

Django otomatis generate struktur folder seperti ini:

todoproject/
  manage.py            # Command-line utility
  todoproject/
      __init__.py      # Package marker
      settings.py      # Konfigurasi project
      urls.py          # URL routing
      wsgi.py          # WSGI entry point
      asgi.py          # ASGI entry point

manage.py itu command center kamu. Semua perintah Django dijalankan lewat file ini - mulai dari bikin database, bikin user admin, sampai menjalankan server.

Menjalankan Server Pertama

Sebelum bikin apapun, coba jalankan server dulu buat pastikan semuanya jalan:

# Jalankan development server
python manage.py runserver

# Output:
# Starting development server at http://127.0.0.1:8000/
# Quit the server with CONTROL-C.

Buka browser, akses http://127.0.0.1:8000/. Kalau muncul halaman roket Django berwarna biru, berarti setup berhasil. Kalau error, cek apakah ada port yang sudah dipakai - coba python manage.py runserver 8080.

Bikin App Todo

Django punya konsep "project" dan "app". Project itu rumahnya, app itu ruangan-ruangannya. Satu project bisa punya banyak app, masing-masing menangani fitur berbeda.

# Bikin app baru bernama 'todo'
python manage.py startapp todo

Ini bikin folder todo/ dengan file-file penting:

todo/
  __init__.py
  admin.py        # Konfigurasi admin panel
  apps.py         # Konfigurasi app
  migrations/     # Database migrations
  models.py       # Database models
  tests.py        # Unit tests
  views.py        # View functions/classes

Jangan lupa daftarkan app baru ini di settings.py:

# todoproject/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todo',  # Tambahkan ini
]

Definisi Model (Database)

Model di Django itu representasi dari tabel database. Kamu definisikan sebagai Python class, dan Django yang bikin SQL-nya otomatis. Ini yang bikin Django powerful - kamu nggak perlu nulis CREATE TABLE sama sekali.

# todo/models.py

from django.db import models

class Task(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    completed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return self.title

Penjelasan field di atas:

  • CharField - Teks pendek dengan batas karakter (wajib max_length)
  • TextField - Teks panjang tanpa batas, blank=True artinya boleh kosong
  • BooleanField - True/False, default-nya False (belum selesai)
  • DateTimeField - Tanggal dan waktu, auto_now_add=True otomatis set saat create
  • ordering = ['-created_at'] - Data terbaru muncul duluan

Migration - Terapkan ke Database

Setelah definisi model, kamu perlu "migrate" supaya perubahan diterapkan ke database. Django menggunakan SQLite sebagai database default - cocok untuk development.

# Buat migration file dari model yang baru dibuat
python manage.py makemigrations todo

# Output: Migrations for 'todo':
#   todo/migrations/0001_initial.py
#     - Create model Task

# Terapkan migration ke database
python manage.py migrate

# Output: Applying todo.0001_initial... OK

Kalau mau lihat SQL yang dijalankan Django secara internal, pakai perintah:

python manage.py sqlmigrate todo 0001

Ini nampilin CREATE TABLE SQL yang sebenarnya. Menarik buat ngerti apa yang terjadi di balik layar.

Admin Panel - Dashboard Otomatis

Salah satu fitur terbaik Django adalah admin panel. Cuma dengan beberapa baris code, kamu udah punya dashboard buat manage data.

# todo/admin.py

from django.contrib import admin
from .models import Task

@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
    list_display = ['title', 'completed', 'created_at']
    list_filter = ['completed', 'created_at']
    search_fields = ['title', 'description']
    list_editable = ['completed']

Bikin superuser dulu buat bisa login ke admin:

python manage.py createsuperuser

# Ikuti prompt:
# Username: admin
# Email: [email protected]
# Password: ********

Jalankan server lagi, buka http://127.0.0.1:8000/admin/, login dengan akun yang baru dibuat. Kamu bakal lihat halaman admin dengan "Tasks" yang siap dikelola. Tambah beberapa task dari sini supaya ada data buat ditampilkan.

Views - Logika Aplikasi

View itu tempat logika aplikasi berjalan. Di Django ada dua cara bikin view: function-based dan class-based. Kita pakai function-based dulu supaya lebih mudah dipahami.

# todo/views.py

from django.shortcuts import render, redirect, get_object_or_404
from .models import Task

def task_list(request):
    tasks = Task.objects.all()
    return render(request, 'todo/task_list.html', {'tasks': tasks})

def task_create(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        description = request.POST.get('description', '')
        if title:
            Task.objects.create(title=title, description=description)
            return redirect('task_list')
    return render(request, 'todo/task_form.html')

def task_toggle(request, task_id):
    task = get_object_or_404(Task, id=task_id)
    task.completed = not task.completed
    task.save()
    return redirect('task_list')

def task_delete(request, task_id):
    task = get_object_or_404(Task, id=task_id)
    task.delete()
    return redirect('task_list')

Fungsi render() menggabungkan template HTML dengan data dari view. Fungsi get_object_or_404() itu shortcut yang otomatis return halaman 404 kalau data nggak ketemu - jadi nggak perlu handle error manual.

URL Routing

URL routing di Django itu seperti peta - kamu definisikan URL pattern yang mengarah ke view tertentu. Ada dua level routing: project-level dan app-level.

# todo/urls.py (BUAT FILE BARU)

from django.urls import path
from . import views

urlpatterns = [
    path('', views.task_list, name='task_list'),
    path('create/', views.task_create, name='task_create'),
    path('toggle//', views.task_toggle, name='task_toggle'),
    path('delete//', views.task_delete, name='task_delete'),
]
# todoproject/urls.py (EDIT FILE YANG UDAH ADA)

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todo.urls')),
]

include('todo.urls') memungkinkan setiap app punya URL routing sendiri. Ini bikin project tetap rapi walaupun punya banyak app.

Template - Tampilan HTML

Template Django menggunakan bahasa template sendiri yang mirip HTML tapi dengan tag khusus. Bikin folder templates di dalam app:

mkdir -p todo/templates/todo

Kenapa nested todo/ dua kali? Karena Django mencari template berdasarkan nama app + nama file. Dengan struktur ini, kamu bisa punya todo/templates/todo/task_list.html dan blog/templates/blog/task_list.html tanpa konflik.

<!-- todo/templates/todo/task_list.html -->

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Todo App - Django</title>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body { font-family: 'Segoe UI', sans-serif; background: #f5f5f5; padding: 20px; }
        .container { max-width: 600px; margin: 0 auto; }
        h1 { color: #333; margin-bottom: 20px; }
        .task-form { background: #fff; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .task-form input[type="text"] { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; margin-bottom: 10px; }
        .task-form textarea { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; margin-bottom: 10px; resize: vertical; }
        .btn { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; }
        .btn-primary { background: #4CAF50; color: #fff; }
        .btn-danger { background: #f44336; color: #fff; }
        .btn-success { background: #2196F3; color: #fff; }
        .task-item { background: #fff; padding: 15px; border-radius: 8px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .task-item.completed { opacity: 0.6; }
        .task-item.completed .task-title { text-decoration: line-through; }
        .task-title { font-size: 16px; font-weight: 500; }
        .task-date { font-size: 12px; color: #999; }
        .task-actions a { margin-left: 8px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>My Todo List</h1>

        <div class="task-form">
            <form method="POST" action="{% url 'task_create' %}">
                {% csrf_token %}
                <input type="text" name="title" placeholder="Task baru..." required>
                <textarea name="description" placeholder="Deskripsi (opsional)" rows="2"></textarea>
                <button type="submit" class="btn btn-primary">Tambah Task</button>
            </form>
        </div>

        {% for task in tasks %}
        <div class="task-item {% if task.completed %}completed{% endif %}">
            <div>
                <div class="task-title">{{ task.title }}</div>
                {% if task.description %}
                <div style="color:#666;font-size:13px;margin-top:4px;">{{ task.description }}</div>
                {% endif %}
                <div class="task-date">{{ task.created_at|date:"d M Y H:i" }}</div>
            </div>
            <div class="task-actions">
                <a href="{% url 'task_toggle' task.id %}" class="btn btn-success">
                    {% if task.completed %}Undo{% else %}Done{% endif %}
                </a>
                <a href="{% url 'task_delete' task.id %}" class="btn btn-danger"
                   onclick="return confirm('Yakin hapus?')">Hapus</a>
            </div>
        </div>
        {% empty %}
        <p style="text-align:center;color:#999;padding:20px;">Belum ada task. Tambahkan yang baru!</p>
        {% endfor %}
    </div>
</body>
</html>

Beberapa hal penting dari template di atas:

  • {% csrf_token %} - Wajib ada di setiap form POST. Ini CSRF protection bawaan Django
  • {% url 'task_create' %} - Generate URL dari nama route. Kalau URL berubah, template otomatis menyesuaikan
  • {% for task in tasks %} - Loop Python di template
  • {% if task.completed %} - Conditional di template
  • {{ task.created_at|date:"d M Y H:i" }} - Format tanggal pakai Django template filter
  • {% empty %} - Block yang ditampilkan kalau list kosong

Template Form (Create Task)

<!-- todo/templates/todo/task_form.html -->

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <title>Tambah Task - Todo App</title>
</head>
<body>
    <h1>Tambah Task Baru</h1>
    <form method="POST">
        {% csrf_token %}
        <p><input type="text" name="title" placeholder="Judul task" required></p>
        <p><textarea name="description" placeholder="Deskripsi"></textarea></p>
        <p><button type="submit">Simpan</button></p>
    </form>
    <a href="{% url 'task_list' %}">Kembali</a>
</body>
</html>

Jalankan Semuanya

Sekarang saatnya test! Pastikan server masih jalan, lalu buka browser:

# Kalau server belum jalan
python manage.py runserver

# Akses di browser:
# http://127.0.0.1:8000/

Kamu bakal lihat halaman Todo List dengan form tambah task di atas. Coba tambahkan beberapa task, tandai sebagai selesai, dan hapus. Semua CRUD (Create, Read, Update, Delete) udah jalan dengan cuma sekitar 100 baris code!

Django Shell - Testing Interaktif

Django punya shell interaktif yang sangat berguna buat testing dan debugging. Bedanya dengan Python shell biasa, Django shell udah load semua model dan konfigurasi.

python manage.py shell

# Di dalam shell:
>>> from todo.models import Task
>>> Task.objects.all()
, ]>

>>> Task.objects.filter(completed=True)
]>

>>> Task.objects.create(title='Task dari shell', description='Testing via shell')


>>> Task.objects.count()
3

Django ORM sangat intuitif kalau kamu udah kenal Python. Filter, exclude, annotate, aggregate - semua bisa dilakukan dengan syntax yang clean.

Custom Template Tag dan Filter

Kadang kamu butuh logic tambahan di template. Django memungkinkan kamu bikin custom template tags dan filters:

# todo/templatetags/todo_tags.py (BUAT FILE BARU)
# Jangan lupa buat __init__.py di folder templatetags

from django import template
from todo.models import Task

register = template.Library()

@register.simple_tag
def pending_count():
    return Task.objects.filter(completed=False).count()

@register.filter
def truncate_words_custom(value, num=10):
    words = value.split()
    if len(words) > num:
        return ' '.join(words[:num]) + '...'
    return value

Di template, pakai seperti ini:

{% load todo_tags %}

<p>Task yang belum selesai: {% pending_count %}</p>
<p>{{ task.description|truncate_words_custom:15 }}</p>

Static Files - CSS, JS, Gambar

Django punya sistem static files yang rapi. Untuk development, cukup taruh file statis di folder todo/static/todo/:

mkdir -p todo/static/todo/css
mkdir -p todo/static/todo/js
/* todo/static/todo/css/style.css */
body { font-family: 'Segoe UI', Tahoma, sans-serif; }
.task-item { transition: all 0.3s ease; }
.task-item:hover { transform: translateX(5px); }

Load di template:

{% load static %}
<link rel="stylesheet" href="{% static 'todo/css/style.css' %}">

Untuk production, kamu perlu jalankan python manage.py collectstatic yang mengumpulkan semua static files ke satu folder yang bisa di-serve oleh nginx atau web server lain.

Management Commands

Django bisa kamu extend dengan custom management commands. Ini sangat berguna buat task automation:

# todo/management/commands/clear_completed.py
# Buat folder: todo/management/ dan todo/management/commands/
# Jangan lupa __init__.py di kedua folder

from django.core.management.base import BaseCommand
from todo.models import Task

class Command(BaseCommand):
    help = 'Hapus semua task yang sudah selesai'

    def handle(self, *args, **options):
        count = Task.objects.filter(completed=True).count()
        Task.objects.filter(completed=True).delete()
        self.stdout.write(
            self.style.SUCCESS(f'Berhasil menghapus {count} task yang sudah selesai')
        )

Jalankan dengan:

python manage.py clear_completed
# Output: Berhasil menghapus 3 task yang sudah selesai

Tips Buat Project Selanjutnya

  • Gunakan Django REST Framework (DRF) kalau kamu mau bikin API. Install dengan pip install djangorestframework dan kamu bisa expose model sebagai REST endpoint dalam hitungan menit
  • Pakai Class-Based Views (CBV) untuk project yang lebih besar. CBV lebih reusable dan punya banyak mixin built-in
  • Pisahkan settings - bikin settings/base.py, settings/local.py, settings/production.py supaya konfigurasi environment nggak campur aduk
  • Pakai PostgreSQL untuk production. SQLite bagus buat development tapi nggak cocok buat banyak concurrent users
  • Deploy dengan Gunicorn + Nginx - development server Django nggak dirancang buat production. Kalau mau deploy, baca juga tutorial tentang membuat REST API yang bisa jadi referensi arsitektur backend

Kesimpulan

Django itu framework yang sangat mature dan well-documented. Dari tutorial ini, kamu udah ngerti cara bikin project, definisi model, bikin view, dan membuat template. Todo app yang kita buat cuma permukaan - Django bisa jauh lebih powerful dari ini.

Langkah selanjutnya yang saya sarankan: coba bikin project kedua dengan fitur authentication (login/register), lalu explore Django REST Framework buat bikin API. Kalau udah familiar, coba deploy ke VPS dengan Gunicorn dan Nginx.

Punya pertanyaan atau stuck di step tertentu? Tulis di kolom komentar di bawah, saya bantu selesaikan!


You may also like


0 Comments


Leave a Reply

Comments with links or spam keywords will be rejected.
Scroll to Top