Django Sollicitatievragen: ORM, Middleware en DRF Diepgaand Behandeld
Django sollicitatievragen over ORM-optimalisatie met FETCH_PEERS, middleware-architectuur en DRF serializer-prestaties. Codevoorbeelden met Django 6.1.

Django sollicitatievragen richten zich op drie fundamentele pijlers die senior kandidaten onderscheiden van de rest: ORM-beheersing, middleware-architectuur en Django REST Framework (DRF) ontwerppatronen. Deze gids behandelt de exacte vragen die technisch recruiters stellen in 2026, inclusief productie-ready codevoorbeelden met Django 6.1 en DRF 3.18.
Django-interviews vragen zelden naar basis CRUD-operaties. De focus is verschoven naar QuerySet-optimalisatie (select_related versus prefetch_related, de nieuwe FETCH_PEERS-modus), aangepast middleware-ontwerp en DRF serializer-prestaties. Kandidaten die N+1 queries kunnen uitleggen en efficiënte viewsets kunnen schrijven, presteren consequent beter dan degenen die alleen generieke views kennen.
Django ORM Sollicitatievragen: QuerySet Optimalisatie
De meest voorkomende Django ORM sollicitatievraag richt zich op het N+1 probleem. Bij een model met foreign key relaties moeten kandidaten demonstreren wanneer select_related versus prefetch_related gebruikt moet worden.
# 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)Het verschil tussen de twee methoden hangt af van het type relatie dat wordt doorlopen.
# 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 voert een SQL JOIN uit en werkt met ForeignKey en OneToOneField. prefetch_related voert een aparte query uit en werkt met ManyToManyField en omgekeerde ForeignKey relaties. Ze door elkaar halen veroorzaakt ofwel onnodige JOINs op grote datasets of het gevreesde N+1 patroon.
Django 6.1: FETCH_PEERS Modus voor Automatische N+1 Preventie
Django 6.1 introduceert een nieuw fetch mode systeem dat N+1 queries op ORM-niveau aanpakt. Bij het itereren over een queryset en toegang tot een gerelateerd veld, haalt FETCH_PEERS dat veld op voor alle instanties in de queryset met een enkele extra query.
# views.py — Django 6.1 FETCH_PEERS mode
from django.db import models
from .models import Book
# Traditional approach: requires explicit prefetch_related
books = Book.objects.prefetch_related("author").all()
# Django 6.1 approach: automatic peer fetching
books = Book.objects.fetch_mode(models.FETCH_PEERS)
for book in books:
print(book.author.name) # Only 2 queries total: books + all authorsDrie fetch modes zijn beschikbaar:
FETCH_ONE(standaard): Haalt het ontbrekende veld alleen voor de huidige instantie opFETCH_PEERS: Haalt het veld op voor alle instanties uit dezelfde QuerySetFETCH_RAISE: GooitFieldFetchBlockedvoor prestatie-kritieke code waar lazy loading moet worden voorkomen
Voor sollicitatiedoeleinden moeten kandidaten beide benaderingen kennen: expliciet select_related/prefetch_related voor fijnmazige controle, en FETCH_PEERS voor automatische optimalisatie bij het itereren over querysets.
Geavanceerde ORM: Custom Managers en QuerySet Chaining
Interviewers vragen kandidaten vaak om een custom manager te schrijven die bedrijfslogica inkapselt. Het doel is te verifiëren dat de kandidaat Djangos manager-patroon begrijpt en herbruikbare query-interfaces kan schrijven.
# 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()De belangrijke vervolgvraag: "Waarom een custom QuerySet gebruiken in plaats van alleen een Manager?" Het antwoord is chaining. Custom QuerySet-methoden kunnen aan elkaar worden gekoppeld, terwijl Manager-methoden niet kunnen worden gekoppeld na de eerste aanroep.
# 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 6.0 introduceerde CompositePrimaryKey voor modellen die meerdere kolommen als primaire sleutel nodig hebben, plus een ingebouwd background tasks framework. Sollicitatievragen over deze features worden steeds gebruikelijker, vooral voor kandidaten die werken met legacy databases of asynchrone verwerkingseisen.
Django Middleware Sollicitatievragen: Request-Response Pipeline
Middleware-vragen testen het begrip van een kandidaat van Djangos request-response levenscyclus. De standaardvraag: "Leg de volgorde uit waarin middleware een request en een response verwerkt."
Het antwoord volgt een strikt patroon. Tijdens een request worden middleware-klassen van boven naar beneden uitgevoerd zoals gedefinieerd in MIDDLEWARE. Tijdens een response worden ze van beneden naar boven uitgevoerd. Deze ui-laag architectuur betekent dat de eerste middleware in de lijst alles omhult.
# 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 responseEen veelgestelde vervolgvraag: "Hoe zou je de middleware-keten kortsluiten?" Het retourneren van een HttpResponse vanuit __call__ vóór het aanroepen van self.get_response(request) stopt de keten volledig. De resterende middleware en de view worden nooit uitgevoerd.
# 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)Middleware Hooks: process_view, process_exception en process_template_response
Naast __call__ ondersteunt Django middleware drie optionele hook-methoden. Interviewers gebruiken deze om de diepte van kennis te peilen.
# 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 wordt uitgevoerd na URL-resolutie maar vóór de view. Het retourneren van None zet de uitvoering voort; het retourneren van een HttpResponse kortsluit. process_exception wordt alleen uitgevoerd bij onafgehandelde exceptions. process_template_response wordt alleen uitgevoerd voor TemplateResponse objecten, niet voor reguliere HttpResponse.
Klaar om je Django gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
DRF Sollicitatievragen: Serializer Prestaties
Django REST Framework serializer-vragen richten zich op geneste serialisatie en de prestatie-implicaties van verschillende benaderingen. De meest gestelde vraag: "Hoe ga je om met geneste relaties zonder N+1 queries te veroorzaken?"
# 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"]De serializer alleen lost de prestaties niet op. De ViewSet moet de queryset optimaliseren.
# 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")
)Zonder select_related en prefetch_related in de ViewSet triggert elke geserialiseerde developer individuele queries voor zijn bedrijf en vaardigheden. Bij een lijst van 50 developers betekent dat 1 + 50 + 50 = 101 queries in plaats van 3.
DRF Custom Permissions en Authenticatie
Een veelgestelde DRF sollicitatievraag: "Schrijf een custom permission die toegang beperkt op basis van de gebruikersrol en de eigenaar van het object."
# 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 ownerDe nuance waar interviewers naar zoeken: has_permission wordt uitgevoerd bij elk verzoek (lijst-niveau), terwijl has_object_permission alleen wordt uitgevoerd wanneer get_object() wordt aangeroepen (detail-niveau). Vergeten om get_queryset te overschrijven voor list views creëert een beveiligingslek waar gebruikers objecten kunnen zien die niet van hen zijn.
Het uitsluitend vertrouwen op has_object_permission zonder de queryset te filteren laat de lijst-endpoint onbeschermd. Combineer altijd object-level permissions met een gefilterde get_queryset om toegangscontrole af te dwingen op zowel lijst- als detail-views.
DRF Throttling en Pagination Patronen
Throttling en pagination zijn standaard vervolgvragen. Interviewers willen zien dat kandidaten productie-ready API-configuratie begrijpen.
# 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=abc123Cursor-gebaseerde pagination presteert beter dan offset pagination op grote datasets omdat het geen totale rijtelling vereist. De afweging: clients kunnen niet naar willekeurige pagina's springen. Dit is het verwachte antwoord wanneer interviewers vragen "Waarom zou je cursor pagination kiezen boven paginanummer pagination?"
Bronnen
- Django 6.1 Release Notes — FETCH_PEERS fetch mode voor automatische N+1 preventie
- Django 6.0 Release Notes — CompositePrimaryKey en Background Tasks framework
- Django REST Framework Documentatie — Serializer en ViewSet patronen
Kernpunten voor Django Sollicitatievoorbereiding
- ORM-optimalisatie: Match de query-methode met het relatietype.
select_relatedvoor ForeignKey/OneToOne,prefetch_relatedvoor ManyToMany en omgekeerde FK. DeFETCH_PEERSmodus van Django 6.1 biedt automatische N+1 preventie bij het itereren over querysets. - Custom QuerySets: Maken chainbare, herbruikbare bedrijfslogica mogelijk. Custom Manager-methoden kunnen niet worden gekoppeld na de eerste aanroep, maar QuerySet-methoden wel.
- Middleware-architectuur: Het request stroomt van boven naar beneden, de response van beneden naar boven. Kortsluiten door een response te retourneren vóór
get_response()is een fundamenteel patroon voor rate limiting, auth checks en request validatie. - DRF serializer-prestaties: Geneste serializers vereisen expliciete queryset-optimalisatie in de ViewSet. Zonder
select_related/prefetch_relatedveroorzaakt serialisatie N+1 queries op schaal. - DRF permissions: Combineer
has_object_permissionmet een gefilterdeget_querysetom toegangscontrole af te dwingen op zowel list als detail endpoints. Object-level permissions alleen laten list views onbeschermd. - Throttling en pagination: Cursor pagination schaalt beter dan offset op grote tabellen. Configureer throttle rates apart voor anonieme en geauthenticeerde gebruikers.
Oefen deze patronen met Django ORM sollicitatievragen en Django middleware vragen op SharpSkill om vertrouwen op te bouwen vóór het echte sollicitatiegesprek.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Zie jij de bug in Django?
Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Geschreven door
Anthony Fillion-MailletOprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 13 september 2026
Tags
Delen
Gerelateerde artikelen

Geavanceerde Django Middleware in 2026: Custom Middleware, Logging en Sollicitatievragen
Uitgebreide gids over Django Middleware in 2026: request-response cyclus, aangepaste middleware-klassen, async middleware, logging-integratie en veelgestelde technische sollicitatievragen.

Django 5.2: Custom Middleware en Signaalverwerking voor Technische Interviews
Django 5.2 middleware en signals beheersen: middleware-pipeline, async middleware, pre_save/post_save signals en veelvoorkomende interviewpatronen.

Django en Celery: Asynchrone Taakverwerking en Sollicitatievragen 2026
Leer Django en Celery configureren voor asynchrone taakverwerking met codevoorbeelden, task routing, Celery Beat, productie-instellingen en sollicitatievragen voor 2026.