Menggunakan ModelSerializer di Django REST Framework (Auto Fields, Konfigurasi Meta, tuple fields, depth)
Kali ini kita membahas lebih detail mengenai ModelSerializer, yang merupakan salah satu cara handal untuk melakukan sebagian besar CRUD API di DRF.
ModelSerializer ini sangat berguna karena membuat kita tidak perlu menuliskan kode repetitif dan rutin jika dilakukan secara manual, sambil tetap memberikan kontrol yang baik terhadap:
- field mana yang diekspos
- field mana yang read-only atau write-only
- bagaimana relasi direpresentasikan
- validasi apa yang diterapkan
Kalau kita paham ModelSerializer dengan baik, kita bisa membangun API yang rapi jauh lebih cepat.
Bagaimana ModelSerializer Membuat Field Secara Otomatis
Saat kita menggunakan:
| |
DRF akan memeriksa model Django kita dan secara otomatis membuat field serializer berdasarkan tipe field modelnya.
Contoh mapping-nya:
models.CharField->serializers.CharFieldmodels.TextField->serializers.CharFieldmodels.BooleanField->serializers.BooleanFieldmodels.DateField->serializers.DateFieldmodels.DateTimeField->serializers.DateTimeFieldmodels.ForeignKey->serializers.PrimaryKeyRelatedField(perilaku default)
Auto-generation ini jadi alasan kenapa ModelSerializer biasanya menjadi pilihan utama kalau endpoint kita berbasis model.
Konfigurasi Meta yang Wajib Kita Tahu
Di ModelSerializer, sebagian besar perilaku dikonfigurasi lewat class Meta di dalamnya.
Opsi yang utama:
model: model Django mana yang terhubung ke serializer inifields: field model mana yang dimasukkan ke output dan input serializerread_only_fields: field yang muncul di output tapi tidak bisa di-submit/diupdate oleh clientextra_kwargs: kustomisasi per-field tanpa deklarasi field manualdepth: level representasi nested otomatis untuk relasi
Contoh sederhana:
| |
Memilih fields: List Eksplisit vs __all__
List Eksplisit (direkomendasikan untuk API)
| |
Kenapa ini lebih aman:
- mencegah field terekspos secara tidak sengaja jika ada perubahan di model
- menjaga API contract tetap stabil
- memudahkan saat melakukan review kode
fields = __all__ (lebih praktis, tapi berisiko)
| |
Berguna untuk prototyping internal dengan cepat, tapi beresiko untuk API production karena field model yang baru bisa ikut terekspos secara tidak sengaja.
Secara umum:
- API publik/production: pakai field dengan list yang eksplisit
- eksperimen cepat lokal:
__all__bisa digunakan sementara
read_only_fields dan extra_kwargs
read_only_fields
Gunakan ini untuk field yang dikelola server seperti id, timestamp, dan value memerlukan komputasi.
| |
Jika client mengirimkan field yang sudah ditandai read only, DRF akan mengabaikannya untuk operasi write.
extra_kwargs
Gunakan ini untuk menyesuaikan field yang dibuat otomatis tanpa harus redeclare setiap field secara manual.
Contoh:
| |
Ini membuat serializer tetap clean sembari tetap memastikan validasinya terkontrol.
Representasi Relasi dan depth
Secara default, objek relasi di ModelSerializer direpresentasikan sebagai primary key.
Maksud dari “Direpresentasikan sebagai primary key” adalah, DRF mengembalikan objek relasi sebagai nilai ID-nya (contohnya, author: 3), bukan sebagai objek nested yang lebih mudah dibaca manusia seperti { "id": 3, "name": "Alice" }.
Contoh output default untuk FK field author:
| |
Menggunakan depth
Kita bisa meminta DRF secara otomatis untuk menampilkan relasi yang nested:
| |
Ini akan menghasilkan data objek relasi yang nested secara otomatis.
Perbandingan: tanpa depth vs depth = 1 vs depth = 2
Asumsikan relasi:
Post->author(FK keAuthor)Author->company(FK keCompany)
Tanpa depth (default, primary key saja):
| |
depth = 1 (hanya relasi langsung yang dinest):
| |
depth = 2 (nest satu level lagi di dalam relasi nested):
| |
Yang perlu diperhatikan:
depthyang lebih tinggi berarti data nested lebih banyakdepthyang lebih tinggi juga bisa berarti query lebih berat dan response lebih besar
Kenapa depth itu praktis tapi terbatas
Kelebihan:
- sangat cepat untuk demo atau tools internal
- tidak perlu mendefinisikan nested serializer di awal
Kekurangan:
- kontrol terhadap field nested jadi kurang eksplisit
- bisa men-trigger query yang berat kalau queryset tidak dioptimasi
- bisa mengekspos lebih banyak data relasi dari yang diinginkan
Untuk API production, nested serializer yang eksplisit biasanya lebih baik daripada terlalu bergantung pada depth.
Latihan Praktik
Latihan ini dibuat tidak berhubungan dengan materi lainnya. Kita akan membuat app baru supaya latihan materi ini tidak bergantung dari materi lain.
Buat dan daftarkan app baru
| |
Tambahkan app ini ke INSTALLED_APPS di config/settings.py:
| |
Buat model sederhana di modelserializer_lab/models.py
| |
Jalankan migration:
| |
Buat serializer di modelserializer_lab/serializers.py
| |
Cek field yang digenerate otomatis di Django shell
| |
| |
Perhatikan bagaimana DRF meng-generate tipe field dan pengaturan validator secara otomatis.
Verifikasi perilaku read_only_fields
| |
Catatan: Secara default, DRF biasanya tidak mengeluarkan validation error saat client mengirim field yang read-only.
- Value yang masuk akan diabaikan.
- Validasi tetap bisa lolos tanpa pesan error.
- Saat save, Django menggunakan nilai yang dikelola database (misalnya auto-increment id dan auto timestamp).
Jadi kalau client mengirim id 999, DRF biasanya akan mengabaikan value itu dan menyimpan data dengan id asli berikutnya.
Verifikasi validasi extra_kwargs
| |
Catatan mengenai peletakan validasi:
- Validasi
extra_kwargsdi sini adalah validasi sisi serializer (layer API). - Validasi sisi serializer berjalan saat
.is_valid()dan menghasilkan error yang API-friendly. - Kalau data dibuat langsung melalui ORM (tanpa serializer), aturan serializer ini tidak akan diterapkan.
- Taruh kondisi / aturan bisnis di level model/database; simpan aturan terkait API di serializer.
Bandingkan fields eksplisit vs __all__
| |
Saat ini outputnya mungkin terlihat mirip. Tetapi nantinya field yang eksplisit tetap lebih aman seiring evolusi model.
Latihan Praktik Untuk depth
Masih di dalam modelserializer_lab, tambahkan rantai relasi untuk memahami depth.
Tambahkan model relasi di modelserializer_lab/models.py
| |
Lalu migrate:
| |
Buat serializer dengan level depth berbeda
File: modelserializer_lab/serializers.py
Jika kita lanjut di file serializer yang sama dari bagian sebelumnya, pastikan import-nya mencakup:
| |
| |
Masukkan test data dan bandingkan outputnya
Pertama, buka Django shell dari root project kita:
| |
Lalu jalankan:
| |
Perhatikan polanya:
- flat serializer:
creatorhanya berupa integer primary key depth = 1:creatormenjadi data object nesteddepth = 2:creatoryang nested juga menyertakanstudiosecara nested
Ini memberi gambaran yang jelas dan terisolasi tentang bagaimana depth meng-ekspansi struktur dari response.
Kesalahan Yang Sering Terjadi
- Menggunakan
fields = "__all__"di API production tanpa meninjau risiko exposure data - Lupa memberi tanda di field yang dikelola server sebagai
read_only_fields - Terlalu banyak memakai
depthdan tanpa sengaja mengembalikan payload nested yang berat - Menganggap
ModelSerializermenghilangkan kebutuhan validasi bisnis - Menyebarkan logika validasi dan transformasi ke banyak tempat dibandingkan menjaga logika level serializer tetap di serializer.
Poin Penting
ModelSerializermeng-generate field dari model secara otomatis dan mempercepat pengembangan CRUD API.- Gunakan
fieldseksplisit untuk kontrak API jangka panjang yang lebih aman. read_only_fieldsdanextra_kwargsmemberi kontrol praktis dengan boilerplate rendah.depthberguna untuk output nested cepat, tapi harus dipakai dengan hati-hati.- Bahkan dengan ModelSerializer, strategi validasi tetap penting.
Foto cover oleh allisonsaeng dari Unsplash
