Pertanyaan Wawancara Django: ORM, Middleware, dan DRF Secara Mendalam
Pertanyaan wawancara Django mencakup optimasi ORM dengan select_related dan prefetch_related, arsitektur middleware, serta performa serializer Django REST Framework, permissions, dan pola pagination.

Pertanyaan wawancara Django di tahun 2026 berfokus pada tiga pilar utama yang membedakan kandidat senior dari yang lain: penguasaan ORM, arsitektur middleware, dan pola desain Django REST Framework (DRF). Panduan ini menguraikan pertanyaan-pertanyaan yang sering diajukan oleh hiring manager, dilengkapi contoh kode siap produksi menggunakan Django 5.2 LTS dan DRF 3.17.
Wawancara Django jarang menanyakan tentang CRUD dasar. Fokusnya telah bergeser ke optimasi QuerySet (select_related vs prefetch_related), desain middleware kustom, dan performa serializer DRF. Kandidat yang mampu menjelaskan masalah N+1 query dan menulis viewset yang efisien secara konsisten mengungguli kandidat yang hanya memahami generic views.
Pertanyaan ORM Django: Optimasi QuerySet
Pertanyaan ORM Django yang paling umum menyasar masalah N+1. Diberikan sebuah model dengan relasi foreign key, kandidat harus mendemonstrasikan kapan menggunakan select_related versus prefetch_related.
# models.py
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=200)
founded_year = models.IntegerField()
class Developer(models.Model):
name = models.CharField(max_length=200)
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="developers")
skills = models.ManyToManyField("Skill", related_name="developers")
class Skill(models.Model):
name = models.CharField(max_length=100)
category = models.CharField(max_length=50)Perbedaan antara kedua metode tersebut terletak pada jenis relasi yang sedang diakses.
# queries.py — Correct approach for ForeignKey (single object)
developers = Developer.objects.select_related("company").all()
# Generates ONE SQL query with JOIN
# SELECT developer.*, company.* FROM developer INNER JOIN company ...
# Correct approach for ManyToMany (multiple objects)
developers = Developer.objects.prefetch_related("skills").all()
# Generates TWO SQL queries:
# 1. SELECT * FROM developer
# 2. SELECT * FROM skill INNER JOIN developer_skills WHERE developer_id IN (...)select_related melakukan SQL JOIN dan bekerja dengan ForeignKey serta OneToOneField. prefetch_related mengeksekusi query terpisah dan bekerja dengan ManyToManyField serta relasi reverse ForeignKey. Kesalahan penggunaan menyebabkan JOIN yang tidak perlu pada dataset besar atau masalah N+1 yang ditakuti.
ORM Lanjutan: Custom Manager dan QuerySet Chaining
Pewawancara sering meminta kandidat untuk menulis custom manager yang mengenkapsulasi logika bisnis. Tujuannya adalah memverifikasi bahwa kandidat memahami pola manager Django dan mampu menulis antarmuka query yang dapat digunakan kembali.
# managers.py
from django.db import models
from django.utils import timezone
class ActiveDeveloperQuerySet(models.QuerySet):
def active(self):
"""Filter developers who logged in within the last 30 days."""
cutoff = timezone.now() - timezone.timedelta(days=30)
return self.filter(last_login__gte=cutoff)
def senior(self):
"""Filter developers with 5+ years of experience."""
return self.filter(years_experience__gte=5)
def by_skill(self, skill_name):
"""Filter developers by a specific skill."""
return self.filter(skills__name=skill_name)
class ActiveDeveloperManager(models.Manager):
def get_queryset(self):
return ActiveDeveloperQuerySet(self.model, using=self._db)
def active(self):
return self.get_queryset().active()Pertanyaan lanjutan yang krusial: "Mengapa menggunakan custom QuerySet daripada hanya Manager?" Jawabannya adalah chaining. Method custom QuerySet dapat di-chain satu sama lain, sedangkan method Manager tidak dapat di-chain setelah pemanggilan pertama.
# usage.py — QuerySet chaining in action
# This works because each method returns a QuerySet
senior_python_devs = (
Developer.active_objects # custom manager
.active() # ActiveDeveloperQuerySet method
.senior() # chains another QuerySet method
.by_skill("Python") # chains a third method
.select_related("company") # standard QuerySet method still works
)Django 5.2 memperkenalkan CompositePrimaryKey, fitur yang telah lama dinantikan untuk model yang membutuhkan primary key multi-kolom. Pertanyaan wawancara tentang fitur ini semakin sering muncul, terutama bagi kandidat yang bekerja dengan database legacy atau skema data warehouse.
Pertanyaan Middleware Django: Pipeline Request-Response
Pertanyaan middleware menguji pemahaman kandidat tentang siklus hidup request-response Django. Pertanyaan standarnya: "Jelaskan urutan eksekusi middleware saat memproses request dan response."
Jawabannya mengikuti pola yang ketat. Saat request masuk, kelas middleware dieksekusi dari atas ke bawah sesuai urutan di MIDDLEWARE. Saat response keluar, eksekusi berlangsung dari bawah ke atas. Arsitektur lapisan bawang ini berarti middleware pertama dalam daftar membungkus semuanya.
# middleware.py
import time
import logging
from django.http import JsonResponse
logger = logging.getLogger(__name__)
class RequestTimingMiddleware:
"""Logs the time taken to process each request."""
def __init__(self, get_response):
self.get_response = get_response # next middleware or view
def __call__(self, request):
start_time = time.monotonic()
response = self.get_response(request) # passes to next layer
duration_ms = (time.monotonic() - start_time) * 1000
logger.info(
"method=%s path=%s status=%d duration=%.2fms",
request.method,
request.path,
response.status_code,
duration_ms,
)
return responsePertanyaan lanjutan yang umum: "Bagaimana cara memotong rantai middleware?" Mengembalikan HttpResponse dari __call__ sebelum memanggil self.get_response(request) menghentikan seluruh rantai. Middleware yang tersisa dan view tidak akan pernah dieksekusi.
# middleware.py — Rate limiting with short-circuit
from django.core.cache import cache
class RateLimitMiddleware:
"""Blocks requests exceeding 100 per minute per IP."""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
ip = request.META.get("REMOTE_ADDR")
cache_key = f"rate_limit:{ip}"
request_count = cache.get(cache_key, 0)
if request_count >= 100:
return JsonResponse( # short-circuits — view never executes
{"error": "Rate limit exceeded. Try again in 60 seconds."},
status=429,
)
cache.set(cache_key, request_count + 1, timeout=60)
return self.get_response(request)Hook Middleware: process_view, process_exception, dan process_template_response
Selain __call__, middleware Django mendukung tiga method hook opsional. Pewawancara menggunakan topik ini untuk mengukur kedalaman pengetahuan kandidat.
# middleware.py — Full middleware with all hooks
class AuditMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
"""Called after URL resolution, before the view executes."""
logger.info("Calling view: %s", view_func.__name__)
return None # returning None continues normal processing
def process_exception(self, request, exception):
"""Called only if the view raises an exception."""
logger.error("View exception: %s", exception, exc_info=True)
return None # returning None lets Django's default handling proceed
def process_template_response(self, request, response):
"""Called if the response has a render() method (TemplateResponse)."""
response.context_data["audit_timestamp"] = time.time()
return response # must return a response with render()process_view dipanggil setelah resolusi URL tetapi sebelum view dieksekusi. Mengembalikan None melanjutkan eksekusi; mengembalikan HttpResponse memotong rantai. process_exception hanya dipanggil saat terjadi exception yang tidak tertangani. process_template_response hanya dipanggil untuk objek TemplateResponse, bukan HttpResponse biasa.
Siap menguasai wawancara Django Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Pertanyaan DRF: Performa Serializer
Pertanyaan serializer Django REST Framework berfokus pada serialisasi bersarang dan implikasi performa dari pendekatan yang berbeda. Pertanyaan yang paling sering diajukan: "Bagaimana menangani relasi bersarang tanpa menyebabkan N+1 query?"
# serializers.py
from rest_framework import serializers
from .models import Developer, Company, Skill
class SkillSerializer(serializers.ModelSerializer):
class Meta:
model = Skill
fields = ["name", "category"]
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = ["name", "founded_year"]
class DeveloperSerializer(serializers.ModelSerializer):
company = CompanySerializer(read_only=True) # nested FK
skills = SkillSerializer(many=True, read_only=True) # nested M2M
class Meta:
model = Developer
fields = ["id", "name", "company", "skills"]Serializer saja tidak menyelesaikan masalah performa. ViewSet harus mengoptimalkan queryset.
# views.py
from rest_framework import viewsets
from .models import Developer
from .serializers import DeveloperSerializer
class DeveloperViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = DeveloperSerializer
def get_queryset(self):
return (
Developer.objects
.select_related("company") # JOIN for FK
.prefetch_related("skills") # separate query for M2M
.order_by("-id")
)Tanpa select_related dan prefetch_related di ViewSet, setiap developer yang diserialisasi memicu query individual untuk company dan skills-nya. Pada daftar 50 developer, itu berarti 1 + 50 + 50 = 101 query, bukan 3.
Custom Permissions dan Authentication DRF
Pertanyaan DRF yang sering muncul: "Tulis custom permission yang membatasi akses berdasarkan role pengguna dan pemilik objek."
# permissions.py
from rest_framework.permissions import BasePermission
class IsOwnerOrAdmin(BasePermission):
"""
Object-level permission:
- Admin users can access any object
- Regular users can only access objects they own
"""
message = "Access restricted to the object owner or admin users."
def has_object_permission(self, request, view, obj):
if request.user.is_staff:
return True
# Assumes the model has an 'owner' field pointing to User
return obj.owner == request.user# views.py — Applying custom permissions
from rest_framework import viewsets, permissions
from .permissions import IsOwnerOrAdmin
class ProjectViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated, IsOwnerOrAdmin]
def get_queryset(self):
# Non-admin users only see their own projects
if self.request.user.is_staff:
return Project.objects.all()
return Project.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user) # auto-assign ownerNuansa yang dicari pewawancara: has_permission berjalan pada setiap request (level daftar), sedangkan has_object_permission hanya berjalan saat get_object() dipanggil (level detail). Lupa meng-override get_queryset untuk list view menciptakan celah keamanan di mana pengguna bisa melihat objek yang bukan milik mereka.
Mengandalkan has_object_permission saja tanpa memfilter queryset membuat endpoint daftar tidak terlindungi. Selalu kombinasikan permission level objek dengan get_queryset yang difilter untuk menegakkan kontrol akses pada view daftar maupun detail.
Pola Throttling dan Pagination DRF
Throttling dan pagination adalah pertanyaan lanjutan yang standar. Pewawancara ingin melihat bahwa kandidat memahami konfigurasi API yang siap produksi.
# settings.py — Production DRF configuration
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": [
"rest_framework.throttling.AnonRateThrottle",
"rest_framework.throttling.UserRateThrottle",
],
"DEFAULT_THROTTLE_RATES": {
"anon": "20/minute", # unauthenticated users
"user": "200/minute", # authenticated users
},
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.CursorPagination",
"PAGE_SIZE": 25,
}# pagination.py — Custom cursor pagination for consistent ordering
from rest_framework.pagination import CursorPagination
class CreatedAtCursorPagination(CursorPagination):
page_size = 25
ordering = "-created_at" # must be a unique, sequential field
cursor_query_param = "cursor" # ?cursor=abc123Pagination berbasis cursor mengungguli offset pagination pada dataset besar karena tidak perlu menghitung total baris. Trade-off-nya: klien tidak bisa melompat ke halaman sembarang. Ini adalah jawaban yang diharapkan saat pewawancara bertanya "Mengapa memilih cursor pagination daripada page number pagination?"
Kesimpulan
Poin-poin utama untuk persiapan wawancara Django:
- Optimasi ORM: Selalu sesuaikan metode query dengan jenis relasi.
select_relateduntuk ForeignKey/OneToOne,prefetch_relateduntuk ManyToMany dan reverse FK. Custom QuerySet memungkinkan logika bisnis yang dapat di-chain dan digunakan kembali. - Arsitektur middleware: Request mengalir dari atas ke bawah, response dari bawah ke atas. Memotong rantai dengan mengembalikan response sebelum
get_response()adalah pola fundamental untuk rate limiting, pengecekan autentikasi, dan validasi request. - Performa serializer DRF: Serializer bersarang memerlukan optimasi queryset secara eksplisit di ViewSet. Tanpa
select_related/prefetch_related, serialisasi menyebabkan N+1 query pada skala besar. - Permissions DRF: Kombinasikan
has_object_permissiondenganget_querysetyang difilter untuk menegakkan kontrol akses pada endpoint daftar maupun detail. Permission level objek saja membuat list view tidak terlindungi. - Throttling dan pagination: Cursor pagination lebih scalable daripada offset pada tabel besar. Konfigurasikan throttle rate secara terpisah untuk pengguna anonim dan terautentikasi.
Latih pola-pola ini dengan pertanyaan wawancara Django ORM dan pertanyaan middleware Django di SharpSkill untuk membangun kepercayaan diri sebelum wawancara sesungguhnya.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Tag
Bagikan
Artikel terkait

Django 5.2: Custom Middleware dan Signal Handling untuk Wawancara Teknis
Panduan lengkap Django 5.2 custom middleware dan signal handling untuk persiapan wawancara teknis. Mencakup request pipeline, async middleware, post_save, pre_save, custom signals, dan praktik terbaik produksi.

Django 6.0 di Tahun 2026: Composite Primary Key, Background Task, dan Pertanyaan Interview
Panduan lengkap Django 6.0 mencakup composite primary key, framework background task bawaan, template partial, dan CSP middleware beserta contoh kode praktis dan persiapan interview.

Django dan Celery: Pemrosesan Tugas Asinkron dan Pertanyaan Wawancara 2026
Panduan lengkap Django Celery dengan contoh kode praktis, task routing, penjadwalan Celery Beat, konfigurasi produksi, dan pertanyaan wawancara teknis 2026.