In Djangos Dokumentation wird empfohlen, statische Dateien durch den Webserver ausliefern zu lassen. Was bedeutet das? Django läuft doch auf dem Webserver.

Im Prinzip geht es darum, Dateien die Django nicht bearbeiten muss, nicht durch den Django-Prozess zu schleifen. Statische Dateien sollen also den direkten Weg von der Festplatte zum Webserver finden (grüne Linie).
Das -- ich nenne es mal -- Problem ist, dass Django eine Funktion bereit stellt, statische Dateien durch Django zu schleifen: How to serve static files.

Hierbei wandern alle statischen Dateien durch den Django-Prozess anstatt dass sie direkt an den Webserver geliefert werden. Das ist ganz klar ineffizient.
Warum gibt's das dann? In erster Linie ist es für Entwickler die den Devserver nutzen gedacht und während der Entwicklung keinen zusätzlichen Webserver zum Static-Serving aufsetzen möchten.
Fazit also: Vermeide Static-Serving durch Django um jeden Preis -- es gibt natürlich Ausnahmen, siehe weiter unten.
PHP macht das doch auch so
Letzens hatte mich ein PHP-Entwickerl auch gefragt, wieso er da nicht Django nehmen kann, dass geht doch auch mit PHP.
Oberes ist ein Zitat aus dem #django-de Channel. PHP macht es aber (unbewusst) genauso wie Django. Statische Dateien werden auch direkt vom Webserver geliefert und nicht erst durch den PHP-Prozessor geschleift. Dieser verarbeitet im Normalfall nur Dateien mit der Endung .php.
Ein Static-Serving durch PHP würde etwa so aussehen, dass der Webserver ein Stylesheet mit 'GET /stylesheet.php' anfordert, und diese Datei das unten gezeigte Script ausführt.
<?php echo file_get_contents('/var/www/static/stylesheet.css'); ?>
Ziemlich dämlich, oder? Aber leider alles schon gesehen. :-(
Spezialisten
Überlasse das Static-Serving einem Server der besser dafür geeignet ist, zum Beispiel nginx oder Lighty.
Den oberen Satz hört man sehr häufig wenn es es Static-Serving geht. Was ist gemeint?
Zuerst einmal, nginx und lighttpd, oder auch liebevoll lighty genannt, sind Webserver, die auf das Ausliefern statischer Dateien optimiert sind. Dabei sind sie nicht unbedingt schneller als der Apache, ihre Stärke liegt in der Auslieferung von mehreren tausend Dateien pro Sekunde, denn dabei sind sie weniger RAM- und CPU-hungrig und skalieren besser.
Es gibt einen Weg, das beste beiden Webservern (Apache für Django, nginx für statische Dateien) herauszuholen. Dabei übernimmt nginx (oder lighty) als Frontend-Server alle Anfragen des Webbrowsers und serviert die statischen Dateien direkt. Anfragen auf dynamische Dateien werden an den Apache-Prozess weitergeleitet, der auf einem anderen Port (also nicht :80) lauscht. (Konfigurationsbeispiel)

Das Ganze ist dann schon ein recht kompliziertes Setup. Meine persönliche Meinung ist, wenn man den Punkt erreicht hat, dass ein spezialisierter Webserver für statische Dateien nötig ist, sollte man den statischen Kram auf eine eigene Maschine auslagern:

Letztendlich ist alles eine Frage des Budgets. Nicht unerwähnt soll bleiben, dass es auch Firmen gibt, die sich auf das Static-Serving spezialisiert haben. Akamai ist ein Vertreter aber auch Amazons S3 Service ist hervorragend dafür geeignet.
Was wäre wenn?
Es gibt natürlich auch das Problem, dass man statische Dateien durch Django schleifen muss. Beispiele:
-
Die Datei soll nur für bestimmte, authentifizierte User verfügbar gemacht werden.
Django stellt für solche Fälle eine Möglichkeit zur Verfügung, dass sich der Apache an Djangos Auth-Backend koppeln kann. Mehr Infos dazu in der Dokumentation. -
Die Datei wird dynamisch erzeugt, zum Beispiel ein PDF-Export der aktuellen Seite.
Vielleicht wäre hier eine Lösung, die Datei im Medienordner zu speichern und einen Location-Header zu dieser Datei zu senden. Dann übernimmt der Webserver wieder das Ausliefern der statischen Dateien und man erhält zudem ein statisches Caching der Dateien.
Jedenfalls, wenn es denn nicht anders möglich ist versuche große Dateien als Iterator an das Response-Objekt zu übergeben. Damit wird nicht die gesamte Datei in den Prozess geladen (bei einer 80MB Datei wäre der wsgi-Prozess dann 90MB+ groß) sondern in kleinen Häppchen (Chunks) durchgeschleift.
Beachte dazu aber, dass die GZip-Middleware diesen Prozess zerstören kann: Ticket #7581. Aber auch dafür gibt es eine einfache, performante Lösung. :-)
Noch ein wichtiger Nachtrag:
Auch wenn in den Bildern mod_python angegeben ist, empfehle ich euch doch ganz stark mod_wsgi als Kleber zwischen Django und Apache. Es ist resoucen schonender, performanter und allgemein sympathischer. Leider aber hat mod_wsgi kein Logo das ich benutzen konnte. ;-)
Mehr dazu
Mehr Lesestoff und vor allem Konfigurations-Beispiele für verschiedene Webserver-Szenarien findest du im deutschsprachigen django-hosting Wiki.