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.

Django Interview-Vorbereitung zu ORM, Middleware und Django REST Framework

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.

Bereit für deine Django-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

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.

Fang an zu üben!

Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.

Tags

#django
#python
#interview
#orm
#middleware
#drf
#rest-api

Teilen

Verwandte Artikel