{{ npm }}
+ +
{{ name }}
+ +{{ class }}
+ {% endblock content %} + ``` + + Perhatikan bahwa kode diatas merupakan kode yang sama dengan kode pada `main.html` pada tutorial sebelumnya. Perbedaannya adalah pada kode diatas, kita menggunakan `base.html` sebagai _template_ utama. + +## Tutorial: Mengubah Primary Key Dari Integer Menjadi UUID + +Untuk mengedepankan _best practice_ dari sisi keamanan aplikasi, terdapat sedikit perubahan yang perlu kamu lakukan pada berkas `models.py` di subdirektori `main/`. Secara _default_, ID dari setiap objek model yang akan kamu buat menggunakan tipe data _integer_ yang _incremental_, dimulai dari 1. Ini dapat menjadi salah satu "pintu masuk" terhadap celah keamanan aplikasi Django kalian, karena dapat dilakukan enumerasi terhadap ID dari objek-objek yang terdapat pada aplikasi. + +Apabila kamu penasaran celah keamanan ini termasuk ke jenis kerentanan apa dan apa dampak yang dapat terjadi, kamu dapat membaca lebih lanjut pada [artikel ini mengenai IDOR](https://portswigger.net/web-security/access-control/idor). Untuk sekarang, kita akan berfokus pada menerapkan _best practice_ untuk mencegah celah keamanan ini. + +:::warning +Apabila kamu sebelumnya sudah menambahkan objek ke modelmu, kamu harus menghapus berkas basis datamu (`db.sqlite3`) terlebih dahulu agar langkah-langkah berikut tidak menimbulkan _error_. +::: + +1. Tambahkan baris ini pada berkas `models.py` di subdirektori `main/`. + +```python +import uuid # tambahkan baris ini di paling atas +... +class MoodEntry(models.Model): + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # tambahkan baris ini + mood = models.CharField(max_length=255) + time = models.DateField(auto_now_add=True) + feelings = models.TextField() + mood_intensity = models.IntegerField() +... +``` + +2. Lakukan migrasi model dengan menjalankan perintah berikut. + + Windows: + ``` + python manage.py makemigrations + python manage.py migrate + ``` + + Unix (Linux/macOS): + ``` + python3 manage.py makemigrations + python3 manage.py migrate + ``` + +## Tutorial: Membuat Form Input Data dan Menampilkan Data Mood Entry Pada HTML + +Sampai saat ini, belum ada data yang ditambahkan dan dimunculkan ke dalam aplikasi. Sekarang, kita akan membuat sebuah _form_ sederhana untuk menginput data _Mood Entry_ pada aplikasi sehingga nantinya kamu dapat menambahkan data baru untuk ditampilkan pada halaman utama. + +1. Buat berkas baru pada direktori `main` dengan nama `forms.py` untuk membuat struktur _form_ yang dapat menerima data _Mood Entry_ baru. Tambahkan kode berikut ke dalam berkas `forms.py`. + + ```python + from django.forms import ModelForm + from main.models import MoodEntry + + class MoodEntryForm(ModelForm): + class Meta: + model = MoodEntry + fields = ["mood", "feelings", "mood_intensity"] + ``` + + **Penjelasan Kode:** + + - `model = MoodEntry` untuk menunjukkan model yang akan digunakan untuk _form_. Ketika data dari _form_ disimpan, isi dari _form_ akan disimpan menjadi sebuah objek `MoodEntry`. + - `fields = ["mood", "feelings", "mood_intensity"]` untuk menunjukkan _field_ dari model `MoodEntry` yang digunakan untuk _form_. _Field_ `time` tidak dimasukkan ke _list_ `fields` karena `time` ditambahkan secara otomatis. + +2. Buka berkas `views.py` yang ada pada direktori `main` dan tambahkan beberapa _import_ berikut pada bagian paling atas. + + ```python + from django.shortcuts import render, redirect # Tambahkan import redirect di baris ini + from main.forms import MoodEntryForm + from main.models import MoodEntry + ``` + +3. Masih di berkas yang sama, buat fungsi baru dengan nama `create_mood_entry` yang menerima parameter `request`. Tambahkan potongan kode di bawah ini untuk menghasilkan _form_ yang dapat menambahkan data _Mood Entry_ secara otomatis ketika data di-_submit_ dari _form_. + + ```python + def create_mood_entry(request): + form = MoodEntryForm(request.POST or None) + + if form.is_valid() and request.method == "POST": + form.save() + return redirect('main:show_main') + + context = {'form': form} + return render(request, "create_mood_entry.html", context) + ``` + + **Penjelasan Kode:** + + - `form = MoodEntryForm(request.POST or None)` digunakan untuk membuat `MoodEntryForm` baru dengan memasukkan _QueryDict_ berdasarkan input dari _user_ pada `request.POST`. + - `form.is_valid()` digunakan untuk memvalidasi isi input dari _form_ tersebut. + - `form.save()` digunakan untuk membuat dan menyimpan data dari _form_ tersebut. + - `return redirect('main:show_main')` digunakan untuk melakukan _redirect_ ke fungsi `show_main` pada _views_ aplikasi `main` setelah data _form_ berhasil disimpan. + +4. Ubahlah fungsi `show_main` yang sudah ada pada berkas `views.py` menjadi seperti berikut. + + ```python + def show_main(request): + mood_entries = MoodEntry.objects.all() + + context = { + 'name': 'Pak Bepe', + 'class': 'PBP D', + 'npm': '2306123456', + 'mood_entries': mood_entries + } + + return render(request, "main.html", context) + ``` + + **Penjelasan Kode:** + + Fungsi `MoodEntry.objects.all()` digunakan untuk mengambil seluruh objek `MoodEntry` yang tersimpan pada _database_. + +5. Buka `urls.py` yang ada pada direktori `main` dan _import_ fungsi `create_mood_entry` yang sudah kamu buat tadi. + + ```python + from main.views import show_main, create_mood_entry + ``` + +6. Tambahkan _path_ URL ke dalam variabel `urlpatterns` pada `urls.py` di `main` untuk mengakses fungsi yang sudah di-_import_ pada poin sebelumnya. + + ```python + urlpatterns = [ + ... + path('create-mood-entry', create_mood_entry, name='create_mood_entry'), + ] + ``` + +7. Buat berkas HTML baru dengan nama `create_mood_entry.html` pada direktori `main/templates`. Isi `create_mood_entry.html` dengan kode berikut. + + ```html + {% extends 'base.html' %} + {% block content %} +