# Django Interview-Fragen: ORM, Middleware und DRF im Detail > Django Interview-Fragen für 2026: ORM-Optimierung, Middleware-Architektur und Django REST Framework. Mit Codebeispielen für Django 5.2 LTS. - Published: 2026-04-03 - Updated: 2026-04-03 - Author: SharpSkill - Tags: django, python, interview, orm, middleware, drf, rest-api - Reading time: 9 min --- Django-Vorstellungsgespräche konzentrieren sich auf drei zentrale Bereiche, die erfahrene Entwickler von Einsteigern unterscheiden: ORM-Beherrschung, Middleware-Architektur und Django REST Framework (DRF) Designmuster. Dieser Leitfaden analysiert die konkreten Fragen, die technische Interviewer im Jahr 2026 stellen, mit produktionsreifen Codebeispielen für Django 5.2 LTS und DRF 3.17. > **Worauf Interviewer tatsächlich achten** > > Django-Interviews behandeln selten grundlegende CRUD-Operationen. Der Fokus liegt auf QuerySet-Optimierung (select_related vs prefetch_related), benutzerdefiniertem Middleware-Design und DRF-Serializer-Performance. Kandidaten, die N+1-Queries erklären und effiziente ViewSets schreiben können, übertreffen konstant jene, die nur generische Views kennen. ## Django ORM Interview-Fragen: QuerySet-Optimierung Die häufigste Django ORM Interview-Frage zielt auf das N+1-Problem ab. Bei einem Modell mit Fremdschlüsselbeziehungen müssen Kandidaten demonstrieren, wann `select_related` gegenüber `prefetch_related` zu verwenden ist. Das N+1-Problem entsteht, wenn eine Abfrage für eine Liste von Objekten ausgeführt wird und anschließend für jedes Objekt eine separate Abfrage für verknüpfte Daten erfolgt. Bei 100 Entwicklern mit jeweils einer Firma würde dies 101 Datenbankabfragen bedeuten statt der optimalen zwei. ```python # 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) ``` Die Unterscheidung zwischen `select_related` und `prefetch_related` basiert auf der Art der Beziehung. ForeignKey- und OneToOne-Beziehungen erfordern `select_related`, da ein einzelnes verknüpftes Objekt über einen SQL-JOIN geladen wird. ManyToMany- und reverse ForeignKey-Beziehungen benötigen `prefetch_related`, da mehrere Objekte in einer separaten Abfrage geladen werden. ```python # 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 (...) ``` Interviewer erwarten, dass Kandidaten erklären können, warum diese Unterscheidung wichtig ist. `select_related` verwendet einen SQL-JOIN und lädt alle Daten in einer einzigen Abfrage. Dies funktioniert effizient für Eins-zu-Eins-Beziehungen. `prefetch_related` führt separate Abfragen aus und verknüpft die Ergebnisse in Python, was bei Many-to-Many-Beziehungen die einzig praktikable Option darstellt. ## Fortgeschrittenes ORM: Custom Managers und QuerySet-Verkettung Eine häufige Folgefrage in Django-Interviews betrifft die Implementierung von wiederverwendbarer Abfragelogik durch Custom Managers und QuerySets. Diese Technik ermöglicht das Kapseln komplexer Filterlogik in benannte Methoden, die sich elegant verketten lassen. ```python # 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() ``` Der Vorteil dieser Architektur liegt in der Kombination von Lesbarkeit und Performance. Jede Methode gibt ein QuerySet zurück, wodurch lazy evaluation erhalten bleibt. Die Datenbankabfrage wird erst ausgeführt, wenn die Daten tatsächlich benötigt werden. ```python # 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 LTS: Zusammengesetzte Primärschlüssel** > > Django 5.2 führte CompositePrimaryKey ein, eine lang erwartete Funktion für Modelle, die mehrspaltige Primärschlüssel benötigen. Interview-Fragen zu dieser Funktion werden häufiger, insbesondere für Kandidaten, die mit Legacy-Datenbanken oder Data-Warehouse-Schemas arbeiten. ## Django Middleware Interview-Fragen: Request-Response-Pipeline Middleware in Django bildet das Rückgrat der Request-Response-Verarbeitung. Jede HTTP-Anfrage durchläuft die Middleware-Schichten in definierter Reihenfolge, bevor sie den View erreicht, und die Antwort durchläuft dieselben Schichten in umgekehrter Reihenfolge. Das Verständnis dieser Architektur ist entscheidend für Django-Interviews. Interviewer fragen häufig nach der Implementierung von Logging, Rate Limiting oder Authentifizierungsprüfungen auf Middleware-Ebene. ```python # 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 response ``` Die `__init__`-Methode wird einmalig beim Serverstart aufgerufen. Die `__call__`-Methode verarbeitet jede einzelne Anfrage. Diese Trennung ermöglicht einmalige Initialisierung teurer Ressourcen. Ein praktisches Beispiel für produktionsrelevante Middleware ist Rate Limiting. Diese Middleware demonstriert das Short-Circuit-Muster, bei dem eine Anfrage abgelehnt wird, bevor sie den View erreicht. ```python # 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 und process_template_response Neben der `__call__`-Methode bietet Django drei zusätzliche Middleware-Hooks für feinere Kontrolle über den Request-Response-Zyklus. Diese Hooks werden in Django-Interviews häufig abgefragt, da sie fortgeschrittenes Verständnis der Framework-Architektur demonstrieren. `process_view` wird nach der URL-Auflösung, aber vor der View-Ausführung aufgerufen. Dies ermöglicht view-spezifische Logik basierend auf der aufgelösten View-Funktion. `process_exception` wird nur aufgerufen, wenn der View eine Exception wirft. Diese Methode ist ideal für zentralisiertes Error-Logging oder benutzerdefinierte Fehlerseiten. `process_template_response` wird aufgerufen, wenn die Antwort eine `render()`-Methode besitzt, typischerweise bei TemplateResponse-Objekten. Dies ermöglicht das Modifizieren des Template-Kontexts nach der View-Ausführung. ```python # 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() ``` Die Rückgabewerte dieser Hooks sind entscheidend. `None` setzt die normale Verarbeitung fort. Ein HttpResponse-Objekt beendet die Verarbeitung und gibt diese Antwort sofort zurück. ## DRF Interview-Fragen: Serializer-Performance Django REST Framework Serializer sind der zentrale Mechanismus zur Datenvalidierung und -transformation. In technischen Interviews konzentrieren sich die Fragen auf verschachtelte Serializer, Performance-Optimierung und die Unterscheidung zwischen verschiedenen Serializer-Typen. Verschachtelte Serializer ermöglichen die Darstellung komplexer Objektbeziehungen in API-Antworten. Die korrekte Konfiguration dieser Serializer in Kombination mit optimierten QuerySets ist ein häufiges Interview-Thema. ```python # 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"] ``` Die ViewSet-Implementierung muss die entsprechenden QuerySet-Optimierungen enthalten. Ohne `select_related` und `prefetch_related` würde jede serialisierte Instanz separate Datenbankabfragen auslösen. ```python # 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") ) ``` Interview-Kandidaten sollten erklären können, warum `read_only=True` bei verschachtelten Serializern wichtig ist. Ohne dieses Flag würde DRF versuchen, verschachtelte Objekte bei Write-Operationen zu erstellen oder zu aktualisieren, was komplexe Validierungslogik erfordert. ## DRF Benutzerdefinierte Berechtigungen und Authentifizierung Das Berechtigungssystem in Django REST Framework operiert auf zwei Ebenen: View-Level und Object-Level. Interview-Fragen konzentrieren sich häufig auf die Implementierung granularer Zugriffskontrollen für Multi-Tenant-Anwendungen. ```python # 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 ``` Die Integration dieser Berechtigung in einen ViewSet demonstriert das Zusammenspiel zwischen QuerySet-Filterung und Object-Level-Permissions. Beide Mechanismen müssen zusammenarbeiten, um vollständige Zugriffskontrolle zu gewährleisten. ```python # 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 owner ``` > **Häufiger DRF-Sicherheitsfehler** > > Das alleinige Verlassen auf has_object_permission ohne QuerySet-Filterung lässt den List-Endpoint ungeschützt. Object-Level-Permissions sollten stets mit einem gefilterten get_queryset kombiniert werden, um Zugriffskontrolle sowohl auf List- als auch Detail-Views durchzusetzen. ## DRF Throttling und Pagination-Muster Produktionsreife APIs benötigen Schutz vor Überlastung und effiziente Datenausgabe bei großen Datensätzen. Django REST Framework bietet integrierte Lösungen für beide Anforderungen. Throttling begrenzt die Anzahl der Anfragen pro Zeiteinheit. Die Konfiguration unterscheidet zwischen authentifizierten und nicht-authentifizierten Benutzern, wobei erstere typischerweise höhere Limits erhalten. ```python # settings.py — Production DRF configuration REST_FRAMEWORK = { "DEFAULT_THROTTLE_CLASSES": [ "rest_framework.throttling.AnonRateThrottle", "rest_framework.throttling.UserRateThrottle", ], "DEFAULT_THROTTLE_RATES": { "anon": "20/minute", "user": "200/minute", }, "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.CursorPagination", "PAGE_SIZE": 25, } ``` Cursor-basierte Pagination bietet Vorteile gegenüber Offset-Pagination bei großen Datensätzen. Sie verhindert das Problem doppelter oder fehlender Einträge bei gleichzeitigen Schreiboperationen und skaliert linear unabhängig von der Offset-Größe. ```python # pagination.py — Custom cursor pagination for consistent ordering from rest_framework.pagination import CursorPagination class CreatedAtCursorPagination(CursorPagination): page_size = 25 ordering = "-created_at" cursor_query_param = "cursor" ``` Die Wahl des Ordering-Feldes ist entscheidend für Cursor-Pagination. Das Feld muss sequenziell und idealerweise eindeutig sein. `created_at` eignet sich gut, solange keine zwei Objekte exakt denselben Zeitstempel haben können. ## Zusammenfassung der wichtigsten Interview-Themen Django-Interviews im Jahr 2026 fokussieren auf praktische Problemlösung statt theoretisches Wissen. Die folgenden Kernkompetenzen werden konsistent geprüft: - **ORM-Optimierung**: Verständnis des N+1-Problems, korrekte Anwendung von `select_related` für ForeignKey und `prefetch_related` für ManyToMany-Beziehungen - **Custom Managers**: Implementierung wiederverwendbarer QuerySet-Methoden mit korrekter Verkettung - **Middleware-Architektur**: Kenntnis aller Hooks (process_view, process_exception, process_template_response) und deren Rückgabewertverhalten - **Rate Limiting**: Implementierung von Short-Circuit-Logik in Middleware - **DRF Serializer**: Verschachtelte Serializer mit optimierten QuerySets - **Berechtigungssystem**: Kombination von View-Level und Object-Level Permissions - **API-Schutz**: Throttling-Konfiguration und Cursor-basierte Pagination Kandidaten, die diese Konzepte mit funktionierenden Codebeispielen demonstrieren können, heben sich deutlich von der Konkurrenz ab. Die hier gezeigten Muster entsprechen den Best Practices für Django 5.2 LTS und DRF 3.17. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/de/blog/django/django-interview-orm-middleware-drf