Python Framework

Django

Django ist das "Batteries-included" Web-Framework für Python. Models, Migrations, ein ORM, Templates, Auth und ein produktionsreifes Admin-Panel sind integriert, sodass Sie Ihre Daten definieren und Django den Rest erledigt.

intermediate16 min readUpdated 16. Sept. 2026
blog/views.py
python
# blog/views.py
from django.shortcuts import get_object_or_404, render

from .models import Post


def post_detail(request, slug):
    post = get_object_or_404(
        Post.objects.select_related("author"),
        slug=slug,
        status=Post.Status.PUBLISHED,
    )
    return render(request, "blog/post_detail.html", {"post": post})
Veröffentlicht
2005
Sprache
Python
Pattern
MTV (Model–Template–View)
Datenbank
ORM mit Migrations
Admin
Integriert
Aktuelle Version
5.x

Warum es wichtig ist

Warum Django alles mitliefert

Batteries included

Das ORM, Migrations, Templates, Forms, Authentifizierung, Sessions und ein Admin-Panel sind direkt enthalten, gemeinsam versioniert und getestet.

Standardmäßig sicher

CSRF-Schutz, Passwort-Hashing, Clickjacking-Header und SQL-Injection-sichere Queries sind aktiviert, sofern Sie diese nicht bewusst deaktivieren.

Ein echtes Admin-Panel gratis

Registrieren Sie ein Model und erhalten Sie ein durchsuchbares, filterbares CRUD-Interface für Mitarbeiter, wodurch interne Tools in wenigen Stunden fertiggestellt sind.

Das Gesamtbild

Model, Template, View

Ein Model besitzt die Daten, ein Template rendert sie und eine View verbindet beides mit einem Request.

Model

Persistieren

Eine Python-Klasse wird auf eine Tabelle gemappt. Felder beschreiben Spalten, Relationen beschreiben Joins und Migrations entwickeln das Schema weiter.

Template

Rendern

Djangos Template-Sprache mischt HTML mit einem bewusst kleinen Satz an Tags und Filtern, wobei Auto-Escaping standardmäßig aktiviert ist.

View

Verarbeiten

Eine View empfängt einen Request und gibt eine Response zurück. Sie fragt das ORM ab, wendet Logik an und wählt ein Template oder einen Statuscode aus.

HTML5 auf einen Blick

Der Django-Werkzeugkasten

Models und ORM

Klassen definieren, Tabellen erhalten. Abfragen mit Python statt mit manuell gebauten SQL-Strings.

URL-Dispatcher

Pfade mit path()-Patterns und benannten Routen auf Views mappen.

Views

Funktionsbasierte Views für Klarheit, klassenbasierte und generische Views für Wiederverwendbarkeit.

Admin

Ein generiertes Backoffice für jedes Model, das Sie registrieren.

Forms

Deklarative Formulare, die validieren, rendern und vor Manipulationen schützen.

Django REST Framework

Serializers, Viewsets und Router verwandeln Models in JSON APIs.

Eine kurze Geschichte

Vom Newsroom-Tool zum Web-Arbeitstier

  1. 2003

    Geboren in einem Newsroom

    Entwickler beim Lawrence Journal-World bauen ein internes Framework, um tägliche Deadlines einzuhalten.

    03
  2. 2005

    Öffentliche Veröffentlichung

    Django wird Open Source und nach dem Jazz-Gitarristen Django Reinhardt benannt.

    05
  3. 2008

    Die Django Software Foundation

    Eine Non-Profit-Organisation übernimmt die Leitung und trennt das Projekt von einzelnen Unternehmen.

    08
  4. 2014

    Migrations im Core

    Schema-Migrations werden zu einem First-Class-Feature und ersetzen Drittanbieter-Tools.

    14
  5. 2019

    Async kommt

    Django 3.0 fügt ASGI-Support hinzu und öffnet die Tür für async Views und Channels.

    19
  6. Heute

    Ein reifer Standard

    Django 5.x kombiniert ein stabiles ORM mit Async-Support und starken Type Hints.

    Heute

Der vollständige Leitfaden

Django: Alles was Sie wissen müssen

Was ist Django?

Django ist ein „Batteries-included“-Web-Framework für Python. Während die meisten Frameworks von Ihnen verlangen, eine Datenbank-Schicht, eine Template-Engine, ein Admin-Panel und ein Authentifizierungssystem selbst auszuwählen, liefert Django all diese Komponenten in einem kohärenten Paket aus. Sie beschreiben Ihre Daten und Ihre Seiten, und das Framework übernimmt die mühsamen, sicherheitskritischen Teile.

Es wurde 2003 für die Redaktion einer Zeitung entwickelt – ein Team, das Features schnell ausliefern musste, ohne unter dem Zeitdruck zusammenzubrechen. Dieser Ursprung ist spürbar. Django setzt auf Konventionen, Explizitheit und die Einstellung „es sollte einen offensichtlichen Weg geben“. Dadurch ist es eine der zuverlässigsten Optionen für inhaltsreiche und datengesteuerte Websites geblieben.

Wenn Sie jemals eine Woche damit verbracht haben, ein ORM, ein Migration-Tool und ein Auth-System miteinander zu verknüpfen, dann ist Django das Framework, das Ihnen diese Woche erspart.

Das MTV-Pattern

Django bezeichnet seine Architektur als MTV: Model, Template, View. Es handelt sich dabei um dasselbe Konzept wie bei MVC, nur mit anderen Bezeichnungen, was viele Anfänger anfangs verwirrt.

  • Ein Model ist eine Python-Klasse, die eine Tabelle und deren Zeilen beschreibt.
  • Ein Template ist eine HTML-Datei mit Platzhaltern, die die Daten rendert.
  • Eine View ist eine Funktion oder Klasse, die einen Request empfängt, Daten von den Models anfordert und eine Response zurückgibt.

Der Controller im klassischen MVC-Sinne ist Django selbst. Der URL-Dispatcher entscheidet, welche View ausgeführt wird, und das Framework vermittelt zwischen den drei Ebenen. Sobald dieses Schema klar ist, wird alles andere in Django zu einem Detail statt zu einem Rätsel.

Modelle und das ORM

Ein Modell ist eine Klasse, die von models.Model erbt. Jedes Attribut ist ein Feld, und jedes Feld wird zu einer Spalte.

# blog/models.py
from django.conf import settings
from django.db import models


class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    body = models.TextField()
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="posts",
    )
    published_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.title

CharField benötigt ein max_length, da es auf einen begrenzten VARCHAR abgebildet wird. TextField ist unbegrenzt. auto_now_add=True setzt einen Wert nur bei der Erstellung, während auto_now=True bei jedem Speichervorgang aktualisiert wird. null steuert die Datenbank und blank steuert die Formularvalidierung; diese sind bewusst getrennt.

Beziehungen sind explizit:

  • ForeignKey ist eine Many-to-One-Beziehung.
  • ManyToManyField erstellt eine Join-Tabelle.
  • OneToOneField ist ein eindeutiger Foreign Key.

Das related_name legt den Reverse Accessor fest, sodass user.posts.all() von der anderen Seite aus funktioniert. Das on_delete-Argument ist erforderlich, da Django sich weigert zu raten, was mit den Kindern passieren soll, wenn ein Elternelement gelöscht wird.

Migrationen

Migrationen sind versionskontrollierte Dateien, die Änderungen an Ihrem Schema beschreiben. Sie schreiben das Model, Django schreibt das SQL.

python manage.py makemigrations blog
python manage.py migrate

makemigrations analysiert Ihre Models und erstellt eine Migration; migrate wendet ausstehende Migrationen auf die Datenbank an. Da die Migrationsdateien in Ihrem Repository liegen, erhält jede Umgebung dasselbe Schema und Änderungen können wie jeder andere Code reviewt werden. Bearbeiten Sie niemals eine bereits angewendete Migration – fügen Sie stattdessen eine neue hinzu.

Querysets und Beziehungen

Das ORM gibt Querysets zurück, die lazy sind: Sie werden erst ausgeführt, wenn Sie über sie iterieren, sie slicen oder auswerten. Diese Lazy-Ausführung ermöglicht es Ihnen, Filter zu verketten und erst bei der finalen Abfrage die Performance-Kosten zu tragen.

Post.objects.filter(status="PB").exclude(author=user).order_by("-published_at")[:10]

Nützliche Queryset-Methoden sind unter anderem filter, exclude, get, first, exists, count, values, values_list, annotate und aggregate. Mit F()-Ausdrücken können Sie auf eine Spalte in der Datenbank verweisen, und Q()-Objekte ermöglichen es Ihnen, OR-Bedingungen zu erstellen.

from django.db.models import Count, Q

published = Post.objects.filter(
    Q(status="PB") | Q(published_at__isnull=False)
).annotate(comment_count=Count("comments"))

Hier spielt das ORM seine Stärken voll aus: Komplexe Abfragen bleiben in Python, werden sicher parametrisiert und lassen sich modular zusammensetzen.

Das N+1-Problem vermeiden

Der am häufigsten vorkommende Performance-Fehler in Django ist die N+1-Query. Dies passiert, wenn Sie innerhalb einer Schleife auf ein verknüpftes Objekt zugreifen, was pro Zeile eine zusätzliche Query auslöst.

# 1 query for posts, then 1 query per post for the author
for post in Post.objects.all():
    print(post.author.username)

select_related fügt Single-Value-Relationen über Joins in die ursprüngliche Query ein, während prefetch_related eine zweite Query ausführt und die Ergebnisse für Multi-Value-Relationen in Python zusammenfügt.

# 1 query for posts joined with author, 1 for the comments
posts = Post.objects.select_related("author").prefetch_related("comments")

Nutzen Sie select_related bei Foreign Keys und One-to-One-Feldern sowie prefetch_related bei Many-to-Many- und inversen Relationen. Wenn sich eine Seite langsam anfühlt, zählen Sie mit der Django Debug Toolbar die Queries, bevor Sie andere Optimierungen vornehmen.

Views: Funktionen und Klassen

Ein View ist jedes aufrufbare Objekt (Callable), das einen Request entgegennimmt und eine Response zurückgibt. Funktionsbasierte Views sind der einfachste Einstiegspunkt.

# blog/views.py
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, render

from .models import Post


def post_list(request):
    posts = Post.objects.filter(status="PB").select_related("author")
    return render(request, "blog/post_list.html", {"posts": posts})


def post_api(request, slug):
    post = get_object_or_404(Post, slug=slug)
    return JsonResponse({"title": post.title, "body": post.body})

Klassenbasierte Views tauschen ein wenig Indirektion gegen Wiederverwendbarkeit ein. ListView, DetailView, CreateView, UpdateView und DeleteView implementieren die Standard-CRUD-Pattern, und Mixins ermöglichen es, Verhalten modular zusammenzusetzen.

from django.views.generic import ListView

from .models import Post


class PostListView(ListView):
    model = Post
    template_name = "blog/post_list.html"
    context_object_name = "posts"
    paginate_by = 10

    def get_queryset(self):
        return Post.objects.filter(status="PB").select_related("author")

Nutzen Sie funktionsbasierte Views für einmalige Logik und generische klassenbasierte Views für Standard-Listen- und Detailseiten. Es ist völlig normal und sinnvoll, beides innerhalb einer Codebase zu mischen.

URLs

Der URL-Dispatcher ordnet einen Pfad einer View zu. Die Patterns befinden sich in urls.py, wobei jede App ihre eigenen definieren kann.

# config/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("admin/", admin.site.urls),
    path("blog/", include("blog.urls")),
]
# blog/urls.py
from django.urls import path

from . import views

app_name = "blog"

urlpatterns = [
    path("", views.post_list, name="post_list"),
    path("<slug:slug>/", views.post_detail, name="post_detail"),
]

Converter wie <int:id> und <slug:slug> validieren und typisieren das erfasste Segment. Benennen Sie Ihre Routes immer und lösen Sie diese mit reverse() oder dem {% url %}-Tag auf, anstatt Pfade hart zu codieren. So bleiben Links auch nach einer Umbenennung funktionsfähig.

Templates

Templates sind HTML mit einer kleinen, bewusst eingeschränkten Sprache. Autoescaping ist standardmäßig aktiviert, was Sie vor XSS schützt.

{% extends "base.html" %}
{% block content %}
  <h1>{{ post.title }}</h1>
  <p>By {{ post.author.username }} on {{ post.published_at|date:"F j, Y" }}</p>
  <div>{{ post.body|linebreaks }}</div>
{% endblock %}

{% extends %} ermöglicht Template-Vererbung, {% include %} teilt Fragmente und Filter wie date, linebreaks und default formatieren Werte. Es gibt keinen beliebigen Python-Code in Templates; wenn ein Template Logik benötigt, gehört diese Logik in den View oder das Model.

Formulare und Validierung

Das Formular-System von Django validiert Eingaben, rendert das HTML und schützt mittels eines CSRF-Tokens vor Manipulationen.

# blog/forms.py
from django import forms

from .models import Post


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ["title", "slug", "body", "status", "published_at"]
        widgets = {"body": forms.Textarea(attrs={"rows": 12})}
# blog/views.py
from django.shortcuts import redirect, render

from .forms import PostForm


def post_create(request):
    if request.method == "POST":
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.save()
            return redirect(post)
    else:
        form = PostForm()

    return render(request, "blog/post_form.html", {"form": form})

Ein ModelForm leitet Felder und Validierungen aus dem Model ab, sodass beide niemals auseinanderlaufen. Clean-Methoden wie clean_slug ermöglichen benutzerdefinierte Regeln, und form.is_valid() sammelt alle Fehler, bevor die Datenbank angesprochen wird.

Das Admin-Interface

Das Admin-Interface ist das am meisten unterschätzte Feature von Django. Registrieren Sie ein Model und Sie erhalten eine durchsuchbare, filterbare und berechtigungsgesteuerte Oberfläche für Ihr Personal.

# blog/admin.py
from django.contrib import admin

from .models import Post


@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    list_display = ["title", "author", "status", "published_at"]
    list_filter = ["status", "created_at"]
    search_fields = ["title", "body"]
    prepopulated_fields = {"slug": ["title"]}
    raw_id_fields = ["author"]
    date_hierarchy = "published_at"

Das ist ein vollständiges internes Tool in nur einem Dutzend Zeilen. Für Content-Websites ist das Admin-Interface oft bereits das eigentliche Produkt. Es dient zudem als Sicherheitsbarriere: Personalberechtigungen, has_add_permission und has_change_permission steuern exakt, was jede Rolle tun darf.

Einstellungen und Apps

Ein Django-Projekt ist eine Sammlung von Apps. Jede App ist ein eigenständiges Paket mit eigenen Models, Views, Templates und Migrations. INSTALLED_APPS listet diese auf, und settings.py enthält die Konfiguration.

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "blog",
]

Halten Sie Einstellungen aus der Versionsverwaltung fern, sofern es sich um Secrets handelt. Lesen Sie diese aus Umgebungsvariablen aus, teilen Sie die Einstellungen pro Umgebung auf, wenn das Projekt wächst, und nutzen Sie django-environ oder pydantic-settings zum Parsen. Die Befehle django-admin startproject und startapp erstellen das Grundgerüst für beide Ebenen, sodass die Struktur immer konsistent bleibt.

Sicherheitsstandards

Die Standardeinstellungen von Django sind so gewählt, dass der sichere Weg auch der einfachste ist:

  • CSRF-Token schützen Formulare, die den Zustand ändern; die middleware lehnt Anfragen ohne diese Token ab.
  • SQL injection wird vermieden, da Querysets Werte parametrisieren.
  • XSS wird minimiert, da Templates Variablen automatisch escapen, sofern Sie dies nicht explizit mit |safe deaktivieren.
  • Passwörter werden mit einem modernen Algorithmus und konfigurierbaren Hashern gehasht.
  • Clickjacking wird durch die X-Frame-Options-middleware blockiert.
  • HTTPS wird in der Produktion über SECURE_SSL_REDIRECT, SESSION_COOKIE_SECURE und CSRF_COOKIE_SECURE erzwungen.

Führen Sie python manage.py check --deploy aus, bevor Sie live gehen. Es markiert die Einstellungen, die Sie vergessen haben, und ist weitaus kostengünstiger als ein Security-Review.

APIs mit Django REST Framework erstellen

Für JSON APIs ist das Django REST Framework (DRF) die Standard-Ergänzung. Ein Serializer beschreibt, wie ein Model in JSON umgewandelt wird und zurück, während ein Viewset zusammen mit einem Router die CRUD-Endpunkte generiert.

# blog/serializers.py
from rest_framework import serializers

from .models import Post


class PostSerializer(serializers.ModelSerializer):
    author = serializers.StringRelatedField()

    class Meta:
        model = Post
        fields = ["id", "title", "slug", "author", "status", "published_at"]
# blog/api.py
from rest_framework import viewsets

from .models import Post
from .serializers import PostSerializer


class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.select_related("author")
    serializer_class = PostSerializer
    lookup_field = "slug"
# blog/urls.py
from rest_framework.routers import DefaultRouter

from .api import PostViewSet

router = DefaultRouter()
router.register("posts", PostViewSet, basename="post")

urlpatterns = router.urls

Serializer validieren die Eingaben analog zu Forms, Viewsets bieten List-, Create-, Retrieve-, Update- und Delete-Funktionen quasi kostenlos an, und DRF kann OpenAPI-Schemas für Ihre API generieren. Das ORM von Django und die Konventionen von DRF sind ein bewährter Weg für produktive APIs.

Testing

Der Test-Runner von Django erstellt eine frische Test-Datenbank und stellt einen Client bereit, der die gesamte Request-Pipeline durchläuft.

# blog/tests.py
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse

from .models import Post


class PostDetailTests(TestCase):
    def setUp(self):
        user = get_user_model().objects.create_user("ada", password="secret")
        self.post = Post.objects.create(
            title="Hello",
            slug="hello",
            body="First post",
            author=user,
            status=Post.Status.PUBLISHED,
        )

    def test_detail_page_renders(self):
        response = self.client.get(reverse("blog:post_detail", args=["hello"]))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Hello")

    def test_missing_post_returns_404(self):
        response = self.client.get(reverse("blog:post_detail", args=["nope"]))
        self.assertEqual(response.status_code, 404)

TestCase kapselt jeden Test in eine Transaktion und führt einen Rollback durch, sodass die Tests isoliert bleiben und schnell ausgeführt werden. Verwenden Sie django.test.Client für Views, das ORM direkt für Models und pytest-django, wenn Sie pytest-Fixtures bevorzugen. Konzentrieren Sie sich darauf, das Verhalten und die Berechtigungen zu testen, nicht die Implementierungsdetails.

Best Practices

  • Halten Sie Models auf Daten und kleine Domain-Methoden fokussiert; lagern Sie die Orchestrierung in Services oder Views aus.
  • Führen Sie immer select_related und prefetch_related aus, wenn ein Template auf Relations zugreift.
  • Nutzen Sie ModelForm und DRF Serializer, damit die Validierung an einem zentralen Ort bleibt.
  • Benennen Sie jede URL und nutzen Sie Reverse-Lookups; hardcoden Sie Pfade niemals in Templates oder im Code.
  • Fügen Sie Datenbank-Indizes für Spalten hinzu, nach denen Sie filtern oder sortieren.
  • Speichern Sie Secrets in Umgebungsvariablen und führen Sie check --deploy vor dem Release aus.
  • Schreiben Sie Migrations als Code-Review-Artefakte und bearbeiten Sie niemals eine bereits angewendete Migration.
  • Testen Sie die Request-Pipeline mit Client und die Domain-Logik direkt.

Häufige Fehler

  • Über ein Queryset iterieren und innerhalb der Schleife auf Relationen zugreifen, was zu N+1 Queries führt.
  • null=True anstelle eines leeren Strings bei einem String-Feld verwenden und anschließend mit None-Prüfungen kämpfen.
  • Business-Logik in Templates auslagern, weil der View zu überladen wirkte.
  • save() in einer Schleife aufrufen, anstatt bulk_create oder bulk_update zu nutzen.
  • on_delete vergessen oder CASCADE wählen, ohne über den möglichen Datenverlust nachzudenken.
  • DEBUG = True und ein hartcodiertes SECRET_KEY in der Production-Umgebung lassen.
  • Das Admin-Interface als Frontend für Endnutzer behandeln, anstatt es als Tool für Mitarbeiter zu betrachten.
  • Abfragen mit len(queryset) anstatt mit .count() durchführen, wodurch jede einzelne Zeile in den Arbeitsspeicher geladen wird.

Wie geht es weiter?

Django bietet dir den vollständigen, konventionellen Weg zu einer produktionsreifen Python-Web-App. Wenn du einen schlankeren Core und mehr Wahlmöglichkeiten bevorzugst, lies als Nächstes den Flask-Guide. Wenn du eine moderne async JSON API baust und die Validierung über Typen lösen möchtest, ist FastAPI die richtige Wahl. Egal wofür du dich entscheidest: Investiere in die zugrunde liegende Datenbank. Indexing, Transaktionen und Query Planning sind wichtiger als das Framework, und die Backend-Roadmap geht hier tiefer ins Detail. Der Guide zu REST APIs behandelt die Design-Regeln, die eine API benutzerfreundlich machen.

In der Praxis

Vier Dateien, die eine Django-App ausmachen

Ein Model, eine View, ein URL-Map und eine Admin-Registrierung bilden den Kernzyklus eines Django-Projekts.

blog/models.py
from django.conf import settings
from django.db import models
from django.urls import reverse


class Post(models.Model):
    class Status(models.TextChoices):
        DRAFT = "DF", "Draft"
        PUBLISHED = "PB", "Published"

    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    body = models.TextField()
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="posts",
    )
    status = models.CharField(
        max_length=2,
        choices=Status.choices,
        default=Status.DRAFT,
    )
    published_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("blog:post_detail", kwargs={"slug": self.slug})

Laden verwandter Objekte

Der Zugriff auf einen Foreign Key innerhalb einer Schleife löst eine Query pro Zeile aus. Laden Sie die Relation vorab, und die gesamte Seite benötigt nur eine einzige Query.

Bevorzugt
posts = Post.objects.select_related("author")

for post in posts:
    print(post.author.username)
Vermeiden
posts = Post.objects.all()

for post in posts:
    # one extra query per iteration (the N+1 problem)
    print(post.author.username)

Umgang mit fehlenden Zeilen

get_object_or_404 verwandelt eine DoesNotExist-Exception in eine korrekte 404-Response und hält die View frei von try/except-Rauschen.

Bevorzugt
from django.shortcuts import get_object_or_404

post = get_object_or_404(Post, slug=slug)
Vermeiden
from django.http import Http404

try:
    post = Post.objects.get(slug=slug)
except Post.DoesNotExist:
    raise Http404

Abwägungen

Ist Django der richtige Standard?

Django optimiert auf Vollständigkeit und Konventionen. Das ist ein Geschenk bei engen Deadlines, aber eine Einschränkung, wenn man etwas sehr Schlankes möchte.

Strengths

  • Alles ist bereits vorhanden

    Auth, Sessions, Forms, ein ORM, Migrations und ein Admin-Panel werden von einem Projekt gewartet, sodass sie ohne Glue-Code zusammenpassen.

  • Sicherheit ist Standard

    Das Framework schützt out-of-the-box gegen die OWASP-Basics, und der dokumentierte Weg, etwas zu tun, ist normalerweise auch der sicherste.

  • Eine riesige, stabile Community

    Zwanzig Jahre an Antworten, Paketen und Stellenanzeigen bedeuten, dass fast jedes Problem eine bewährte Lösung hat.

Trade-offs

  • Die Lernkurve ist spürbar

    Settings, Apps, das ORM und die Template-Sprache sind viel Stoff auf einmal. Das Framework belohnt Geduld mehr als schnelle Experimente.

  • Es ist bewusst monolithisch

    Django setzt eine relationale Datenbank und eine server-gerenderte Architektur oder eine API voraus. Microservices und exotische Stacks widersprechen oft dem Design.

  • Async-Support ist noch jung

    Das ORM ist weitgehend synchron, daher erfordert die Mischung von async Views mit Datenbankarbeit Sorgfalt und Threads.

Häufig gestellte Fragen

Häufig gestellte Fragen

Keep learning

Related topics from the roadmap.

$ Lernen Sie jetzt

Bereit, Django zu lernen?

Unser interaktives Tutorial führt Sie Schritt für Schritt durch Django — mit Quizzen und echtem Code, den Sie im Browser ausführen können.