Warum führt die Einstellung DEBUG = False dazu, dass mein Zugriff auf statische Django-Dateien fehlschlägt?

356

Ich baue eine App mit Django als Arbeitspferd. Bisher war alles in Ordnung - spezifizierte Datenbankeinstellungen, konfigurierte statische Verzeichnisse, URLs, Ansichten usw. Aber in dem Moment, in dem ich meine eigenen schönen und benutzerdefinierten 404.html- und 500.html-Seiten rendern wollte, begannen sich Probleme zu schleichen.

Ich habe die Dokumente zur benutzerdefinierten Fehlerbehandlung gelesen und die erforderlichen Konfigurationen in UrlsConf festgelegt, entsprechende Ansichten erstellt und die 404.html und die 500.html zum Vorlagenverzeichnis meiner App hinzugefügt (auch in der settings.py angegeben).

Aber die Dokumente sagen you can actually view custom error views until Debug is Off, also habe ich es ausgeschaltet, um meine Sachen zu testen, und dann wird es wahnsinnig!

Ich kann nicht nur die benutzerdefinierte 404.html nicht anzeigen (tatsächlich wird sie geladen, sondern weil meine Fehlerseiten jeweils eine grafische Fehlermeldung enthalten - wie ein schönes Bild), wird die Quelle der Fehlerseite geladen, aber nichts anderes wird geladen! Nicht einmal verknüpftes CSS oder Javascript!

Im Allgemeinen werden nach dem Festlegen DEBUG = Falsealle Ansichten geladen, aber alle verknüpften Inhalte (CSS, Javascript, Bilder usw.) werden nicht geladen! Was ist los? Fehlt etwas an statischen Dateien und der DEBUGEinstellung?

nemesisfixx
quelle
Wie hostest du? Lokaler Computer mit dem Testserver?
j_syk
lokaler Computer mit Testserver. Grundsätzlich möchte ich sehen, wie meine benutzerdefinierte Fehlerbehandlung funktioniert, indem Szenarien wie der Zugriff auf nicht vorhandene Seiten lokal simuliert und Laufzeitfehler verursacht werden. Mein statischer Inhalt wird jedoch nicht geladen.
Nemesisfixx
Entweder kann es auf Serverebene wie hier durchgeführt werden oder es kann auf Django-Ebene durch Hinzufügen von URL-Mustern behandelt werden. Ich fand diese Frage unten für das gleiche Problem. stackoverflow.com/questions/6405173/…
Pankaj Anand

Antworten:

353

Wenn das Debug deaktiviert ist, verarbeitet Django keine statischen Dateien mehr für Sie - Ihr Produktionswebserver (Apache oder so) sollte sich darum kümmern.

Marek Sapota
quelle
3
Dies beruhigt meine Neugier, also macht es jetzt Sinn, und ich kann mich tatsächlich mit Apache darum kümmern, wenn es dann nötig ist. Ich hatte gedacht, es sei ein Problem mit meinen eigenen Einstellungen. Danke
nemesisfixx
5
Ich fand diese Antwort sehr hilfreich. Nur für den Fall, dass sich jemand anderes in derselben Situation befindet (mit Google App Engine für die App mit nonrel django): Vergessen Sie nicht, app.yaml zu aktualisieren.
Lyndsey Ferguson
3
Handler: - URL: / static static_dir: static
Lyndsey Ferguson
475

Wenn Sie den statischen Server weiterhin lokal bedienen müssen (z. B. zum Testen ohne Debug), können Sie devserver im unsicheren Modus ausführen:

manage.py runserver --insecure
Dmitry Shevchenko
quelle
6
Während dieses Flag funktioniert, dient es nicht dem Inhalt aus dem Collectstatic-Ordner
Howie
5
Das ist Magie. Vielen Dank, Sir, Sie sind ein Held. Diese Antwort sollte mit der akzeptierten Antwort zusammengeführt werden, da sie das Problem löst, ohne statisch auf eine andere Weise als Django selbst dienen zu müssen.
Depado
1
Das war alles was ich brauchte. Obwohl die beste Vorgehensweise darin besteht, Umgebungsvariablen zu verwenden, um zwischen Entwicklungs- und Produktionsumgebung und Debug-Umschaltung zu unterscheiden.
Neeraj Gupta
1
Bitte beachten Sie: Das funktioniert NICHT mit ManifestStaticFilesStorage als code.djangoproject.com/ticket/19295
Andrea Rabbaglietti
9
Kann mir jemand sagen, was daran so unsicher ist
Kavi Vaidya
36

Mit WhiteNoise können Sie statische Dateien in der Produktion bereitstellen .

Installieren:

pip install WhiteNoise

Und ändern Sie Ihre wsgi.py- Datei in folgende Datei:

from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

Und du kannst loslegen!

Gutschrift zum kreativen Blog des Lenkers .

ABER es wird wirklich nicht empfohlen, statische Dateien auf diese Weise in der Produktion bereitzustellen. Ihr Produktionswebserver (wie Nginx) sollte sich darum kümmern.

Johnny Zhao
quelle
1
Klingt interessant, hat aber bei mir nicht funktioniert, indem ich nur diese Zeile zur wgsi.pyDatei hinzugefügt habe . Die von Ihnen verlinkte Dokumentation enthält anscheinend weitere Anweisungen zur Verwendung von WhiteNoise. Ich werde andere Möglichkeiten ausprobieren und dich hier aktualisieren.
DarkCygnus
+1, da dies mich schließlich zur Lösung führte. Ich habe eine Antwort hinzugefügt , in der ich die zusätzlichen Schritte angegeben habe, die ich unternommen habe, damit es tatsächlich funktioniert.
DarkCygnus
manage.py runserver --insecurehat bei mir nicht funktioniert. Dieser tut es jedoch.
Jee
3
Beachten Sie, dass sich die Konfiguration mit WhiteNoise Release 4.0 geändert hat. Fügen Sie diese Zeilen nicht zu wsgi.py hinzu. Fügen Sie stattdessen einfach 'whitenoise.middleware.WhiteNoiseMiddleware'Middleware hinzu. Siehe Versionshinweise aus dem Changelog
Doug Harris
Warum wird * nicht empfohlen? Ich benutze es seit Jahren auf mehreren Websites, funktioniert super. Sogar Heroku verwendet es in ihrer Django-Vorlage.
Omar Gonzalez
33

In urls.py habe ich diese Zeile hinzugefügt:

from django.views.static import serve 

Fügen Sie diese beiden URLs in URL-Mustern hinzu:

url(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}), 
url(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}), 

und sowohl statische als auch Mediendateien waren zugänglich, wenn DEBUG = FALSE.
Ich hoffe es hilft :)

Stathoula
quelle
Wenn es fertig ist Admin Panel CSS nicht geladen?
Thusitha Deepal
Ja. Der einzige, der funktioniert !! Vielen Dank.
DrGeneral
GENIAL! Vergessen Sie nicht, STATIC_ROOT und manage.py collectstatic festzulegen.
DomingoR
2
Heutzutage ersetzen url(durchre_path(
Leopd
19

Wenn Sie in der Entwicklung die statische Serve-Ansicht verwenden, muss DEBUG = True sein:

Warnung

Dies funktioniert nur, wenn DEBUG True ist.

Das liegt daran, dass diese Ansicht äußerst ineffizient und wahrscheinlich unsicher ist. Dies ist nur für die lokale Entwicklung vorgesehen und sollte niemals in der Produktion verwendet werden.

Docs: Bereitstellen statischer Dateien in Developent

BEARBEITEN: Sie können einige URLs hinzufügen, um Ihre 404- und 500-Vorlagen zu testen. Verwenden Sie einfach die generische Ansicht direct_to_template in Ihren URLs.

from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
    ('^404testing/$', direct_to_template, {'template': '404.html'})
)
j_syk
quelle
1
Wie kann man dann die statischen Dateien in der Produktion bereitstellen? NVM, das habe ich gerade gesehen. Vielen Dank.
Sie würden Ihren Webserver so einrichten, dass er ein bestimmtes Verzeichnis hostet. Am häufigsten verwenden Sie Apache oder Nginx. Die Docs gehen ein bisschen darauf ein.
j_syk
danke @j_syk, ich hatte bereits versucht, die 404.html und 500.html über einen anderen fehlerfreien Mechanismus anzuzeigen, ähnlich dem, was Sie vorschlagen. Aber ich wollte wissen, ob es absolut unmöglich ist, meine Seiten so zu rendern, wie sie es in der Produktion tun würden, während sie nur auf meinem Testserver ausgeführt werden - die Delegation der statischen Dateibehandlung an Apache, wenn Debug ausgeschaltet ist, regelt dies für mich. Vielen Dank für Ihren Beitrag.
Nemesisfixx
@mcnemesis Ich bin mir nicht sicher, was genau passieren wird - aber versuchen Sie, TEMPLATE_DEBUG = False und DEBUG = True zu setzen. Wenn Sie die hübschen Fehler ausschalten, bin ich mir nicht sicher, ob es stattdessen zu den 404/500 Vorlagen geht
j_syk
Wie erwartet hat dies keine positiven Ergebnisse gebracht. Aber trotzdem danke.
Nemesisfixx
17

Johnnys Antwort ist großartig, hat aber für mich immer noch nicht funktioniert, indem ich nur die dort beschriebenen Zeilen hinzugefügt habe. Basierend auf dieser Antwort waren die Schritte, die tatsächlich für mich funktionierten, wo:

  1. Installieren Sie WhiteNoise wie beschrieben:

    pip install WhiteNoise
  2. Erstellen Sie die STATIC_ROOTVariable und fügen Sie WhiteNoise zu Ihrer MIDDLEWAREVariablen hinzu in settings.py:

    #settings.py
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'whitenoise.middleware.WhiteNoiseMiddleware', #add whitenoise
        'django.contrib.sessions.middleware.SessionMiddleware',
        ...
    ]
    
    #...
    
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') ##specify static root
  3. Ändern Sie dann Ihre wsgi.pyDatei wie in Johnnys Antwort erläutert:

    #wsgi.py
    from django.core.wsgi import get_wsgi_application
    from whitenoise.django import DjangoWhiteNoise
    
    application = get_wsgi_application()
    application = DjangoWhiteNoise(application)
  4. Stellen Sie danach Ihre Änderungen auf Ihrem Server bereit (mit git oder was auch immer Sie verwenden).

  5. Führen Sie collectstaticabschließend die Option manage.pyauf Ihrem Server aus. Dadurch werden alle Dateien aus Ihren statischen Ordnern in das STATIC_ROOTzuvor angegebene Verzeichnis kopiert :

    $ python manage.py collectstatic

    Sie sehen nun einen neuen Ordner mit dem Namen staticfiles, der solche Elemente enthält.

Nachdem Sie diese Schritte ausgeführt haben, können Sie jetzt Ihren Server ausführen und Ihre statischen Dateien im Produktionsmodus anzeigen.

Update: Falls Sie Version <4 hatten, zeigt das Änderungsprotokoll an, dass es nicht mehr erforderlich ist, das WSGI_APPLICATION = 'projectName.wsgi.application'in Ihrer settings.pyDatei zu deklarieren .

DarkCygnus
quelle
Ich habe es entsprechend gemacht, und bei der Entwicklung hat es gut funktioniert, aber nicht in der Produktion. Habe immer noch das gleiche Problem, wenn DEBUG == False
Anna Huang
@AnnaHuang Was meinst du mit Entwicklung und Produktion? Haben Sie separate Umgebungen oder Maschinen? Sind sie gleich konfiguriert?
DarkCygnus
13

Sie können statische Dateien in einer Produktions-Django-App sicher und ohne Daten bereitstellen DEBUG=True.

Verwenden Sie dj_static in Ihrer WSGI-Datei ( github ) , anstatt Django selbst zu verwenden :

# requirements.txt:

...
dj-static==0.0.6


# YOURAPP/settings.py:

...
STATIC_ROOT = 'staticdir'
STATIC_URL = '/staticpath/'

# YOURAPP/wsgi.py:

...
from django.core.wsgi import get_wsgi_application
from dj_static import Cling

application = Cling(get_wsgi_application())
Robin Winslow
quelle
2
Ich habe seitdem Whitenoise entdeckt , das möglicherweise mehr Funktionen bietet.
Robin Winslow
7

Öffnen Sie einfach Ihre Projekt-URLs.py und suchen Sie diese if-Anweisung.

if settings.DEBUG:
    urlpatterns += patterns(
        'django.views.static',
        (r'^media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )

Sie können settings.DEBUG auf True ändern und es wird immer funktionieren. Wenn Ihr Projekt jedoch etwas Ernstes ist, sollten Sie über andere oben erwähnte Lösungen nachdenken.

if True:
    urlpatterns += patterns(
        'django.views.static',
        (r'^media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )

In Django 1.10 können Sie so schreiben:

urlpatterns += [ url(r'^media/(?P<path>.*)$', serve, { 'document_root': settings.MEDIA_ROOT, }), url(r'^static/(?P<path>.*)$', serve, { 'document_root': settings.STATIC_ROOT }), ]
Sergey Luchko
quelle
3
Ihr Code ist korrekt, aber in Django 1.10 ist die Konfiguration für Medien und statisch: urlpatterns + = [url (r '^ media / (? P <Pfad>. *) $', Serve, {'document_root': settings .MEDIA_ROOT,}), URL (r '^ static / (? P <Pfad>. *) $', Serve, {'document_root': settings.STATIC_ROOT}),]
Roberth Solís
6

Sie können dies auf viele verschiedene Arten debuggen. Hier ist mein Ansatz.

localettings.py:

DEBUG = False
DEBUG404 = True

urls.py:

from django.conf import settings
import os

if settings.DEBUG404:
    urlpatterns += patterns('',
        (r'^static/(?P<path>.*)$', 'django.views.static.serve',
         {'document_root': os.path.join(os.path.dirname(__file__), 'static')} ),
    )

Lesen Sie unbedingt die Dokumente;)

https://docs.djangoproject.com/de/2.0/howto/static-files/#limiting-use-to-debug-true

Conrado
quelle
0

Die Unterstützung für Argumente der Zeichenfolgenansicht für url () ist veraltet und wird in Django 1.10 entfernt

Meine Lösung ist nur eine kleine Korrektur der obigen Conrado-Lösung.

from django.conf import settings
import os
from django.views.static import serve as staticserve

if settings.DEBUG404:
    urlpatterns += patterns('',
        (r'^static/(?P<path>.*)$', staticserve,
            {'document_root': os.path.join(os.path.dirname(__file__), 'static')} ),
        )
be_good_do_good
quelle
0

Es ist zwar nicht am sichersten, aber Sie können den Quellcode ändern. Navigieren Sie zuPython/2.7/site-packages/django/conf/urls/static.py

Dann bearbeiten Sie wie folgt:

if settings.DEBUG or (prefix and '://' in prefix):

Wenn sich settings.debug==Falsedies nicht auf den Code auswirkt, versuchen Sie auch nach dem Ausführen python manage.py runserver --runserver, statische Dateien auszuführen.

HINWEIS : Informationen sollten nur zum Testen verwendet werden

Natuto
quelle
0

Ich habe die folgenden Änderungen an meinem Projekt / urls.py vorgenommen und es hat bei mir funktioniert

Fügen Sie diese Zeile hinzu: aus django.conf.urls Import-URL

und füge hinzu: url (r '^ media / (? P. *) $', serve, {'document_root': settings.MEDIA_ROOT,}) in urlpatterns.

Namrata Sharma
quelle