Pourquoi le paramètre DEBUG = False fait échouer mon accès aux fichiers statiques django?

356

Je crée une application en utilisant Django comme cheval de bataille. Tout s'est bien passé jusqu'à présent - paramètres de base de données spécifiés, répertoires statiques configurés, URL, vues, etc. Mais les problèmes ont commencé à se faufiler au moment où je voulais rendre mes propres pages 404.html et 500.html.

J'ai lu les documents sur la gestion des erreurs personnalisées et défini les configurations nécessaires dans UrlsConf, créé des vues correspondantes et ajouté le 404.html et le 500.html au répertoire de modèles de mon application (spécifié également dans settings.py).

Mais les docs disent you can actually view custom error views until Debug is Off, donc je l'ai éteint pour tester mes trucs, et c'est à ce moment que les trucs deviennent fous!

Non seulement je ne parviens pas à afficher le 404.html personnalisé (en fait, il se charge, mais parce que mes pages d'erreur contiennent chacune un message d'erreur graphique - comme une belle image), la source de la page d'erreur se charge, mais rien d'autre ne se charge! Pas même lié CSS ou Javascript!

Généralement, une fois que j'ai défini DEBUG = False, toutes les vues se chargeront, mais tout contenu lié (CSS, Javascript, Images, etc.) ne se chargera pas! Que ce passe-t-il? Y a-t-il quelque chose qui manque, concernant les fichiers statiques et le DEBUGréglage?

nemesisfixx
la source
Comment hébergez-vous? Machine locale avec le serveur de test?
j_syk
machine locale avec serveur de test. Je veux essentiellement voir comment ma gestion des erreurs personnalisée fonctionnerait en simulant localement des scénarios tels que l'accès à des pages non existantes et des erreurs d'exécution - mais mon contenu statique ne se chargera pas.
nemesisfixx
Soit cela peut être fait au niveau du serveur comme ici ou il peut être géré au niveau de Django en ajoutant urlpattern. J'ai trouvé cette question ci-dessous pour le même problème. stackoverflow.com/questions/6405173/…
Pankaj Anand

Réponses:

353

Avec le débogage désactivé, Django ne traitera plus les fichiers statiques pour vous - votre serveur Web de production (Apache ou quelque chose) devrait s'en occuper.

Marek Sapota
la source
3
En fait, cela installe ma curiosité, alors maintenant cela a du sens, et je peux en effet m'en occuper avec Apache si besoin est. J'avais pensé que c'était un problème avec mes propres paramètres. Merci
nemesisfixx
5
J'ai trouvé cette réponse très utile. Juste au cas où quelqu'un d'autre serait dans ma même situation (en utilisant Google App Engine pour l'application avec Django non reliée): n'oubliez pas de mettre à jour app.yaml.
Lyndsey Ferguson
3
gestionnaires: - url: / static static_dir: static
Lyndsey Ferguson
476

Si vous avez toujours besoin de serveur statique local (par exemple pour les tests sans débogage), vous pouvez exécuter devserver en mode non sécurisé:

manage.py runserver --insecure
Dmitry Shevchenko
la source
6
Bien que ce drapeau fonctionne, il ne sert pas le contenu du dossier
collectstatic
5
C'est magique. Merci monsieur, vous êtes un héros. Cette réponse doit être fusionnée avec la réponse acceptée car elle résout le problème sans avoir à servir statique en utilisant une autre manière que django lui-même.
Depado
1
C'était tout ce dont j'avais besoin. Bien que la meilleure pratique serait d'utiliser la variable d'environnement pour différencier l'environnement de développement et de production et la bascule de débogage.
Neeraj Gupta
1
Remarque: cela ne fonctionnera PAS avec ManifestStaticFilesStorage en tant que code.djangoproject.com/ticket/19295
Andrea Rabbaglietti
9
quelqu'un peut-il me dire ce qui est si peu sûr à ce sujet
Kavi Vaidya
36

Vous pouvez utiliser WhiteNoise pour servir des fichiers statiques en production.

Installer:

pip install WhiteNoise

Et changez votre fichier wsgi.py en ceci:

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

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

Et vous êtes prêt à partir!

Crédit au blog créatif du guidon .

MAIS, il n'est vraiment pas recommandé de servir des fichiers statiques de cette façon en production. Votre serveur Web de production (comme nginx) devrait s'en occuper.

Johnny Zhao
la source
1
Cela semble intéressant, mais n'a pas fonctionné pour moi en ajoutant simplement cette ligne au wgsi.pyfichier. La documentation que vous avez liée semble donner d'autres instructions pour utiliser WhiteNoise. Je vais essayer d'autres moyens et vous mettre à jour ici.
DarkCygnus
+1 car c'est ce qui m'a finalement conduit à la solution. J'ai ajouté une réponse où j'ai inclus les étapes supplémentaires que j'ai prises pour que cela fonctionne réellement.
DarkCygnus
manage.py runserver --insecuren'a pas fonctionné pour moi. Mais celui-ci le fait.
Jee
3
Notez qu'avec la version 4.0 de WhiteNoise, la configuration a changé. N'ajoutez pas ces lignes à wsgi.py. Au lieu de cela, ajoutez simplement 'whitenoise.middleware.WhiteNoiseMiddleware'au middleware. Voir les notes de version du journal des modifications
Doug Harris
Pourquoi * n'est-il pas recommandé? Je l'utilise depuis des années sur plusieurs sites, fonctionne très bien. Même Heroku l'utilise dans son modèle Django.
Omar Gonzalez
33

Dans urls.py, j'ai ajouté cette ligne:

from django.views.static import serve 

ajoutez ces deux URL dans les motifs d'URL:

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

et les fichiers statiques et multimédias étaient accessibles lorsque DEBUG = FALSE.
J'espère que cela aide :)

stathoula
la source
Quand il a fait le panneau d'administration css ne se charge pas ??
Thusitha Deepal
Oui. Le seul qui fonctionne !! Merci.
DrGeneral
IMPRESSIONNANT! N'oubliez pas de définir STATIC_ROOT et manage.py collectstatic.
DomingoR
2
Remplace aujourd'hui url(parre_path(
Leopd
19

Si vous utilisez la vue de service statique dans le développement, vous devez avoir DEBUG = True:

Attention

Cela ne fonctionnera que si DEBUG est True.

C'est parce que cette vue est extrêmement inefficace et probablement peu sûre. Ceci est uniquement destiné au développement local et ne doit jamais être utilisé en production.

Docs: servir des fichiers statiques en développement

EDIT: Vous pouvez ajouter des URL juste pour tester vos modèles 404 et 500, utilisez simplement la vue générique direct_to_template dans vos URL.

from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
    ('^404testing/$', direct_to_template, {'template': '404.html'})
)
j_syk
la source
1
Comment peut-on alors servir les fichiers statiques en production? NVM, je viens de voir ça. Merci.
vous devez configurer votre serveur Web pour héberger un répertoire spécifique. Le plus souvent, vous utiliseriez Apache ou Nginx. Les Docs y entrent un peu.
j_syk
merci @j_syk, j'avais déjà essayé cette approche de visualisation des 404.html et 500.html via un autre mécanisme de non-erreur similaire à ce que vous suggérez. Mais je voulais savoir s'il était totalement impossible que mes pages s'affichent correctement comme elles le feraient en production, tout en fonctionnant simplement sur mon serveur de test - la délégation de la gestion des fichiers statiques à Apache lorsque le débogage est désactivé le règle pour moi. Merci d'avoir contribué.
nemesisfixx
@mcnemesis Je ne sais pas exactement ce qui va se passer, mais essayez de définir TEMPLATE_DEBUG = False et DEBUG = True. Si vous désactivez les jolies erreurs, je ne sais pas si cela va aux modèles 404/500 à la place
j_syk
comme prévu, cela n'a donné aucun résultat positif, mais merci encore.
nemesisfixx
17

La réponse de Johnny est excellente, mais n'a toujours pas fonctionné pour moi simplement en ajoutant les lignes décrites ici. Sur la base de cette réponse, les étapes qui ont réellement fonctionné pour moi où:

  1. Installez WhiteNoise comme décrit:

    pip install WhiteNoise
  2. Créez la STATIC_ROOTvariable et ajoutez WhiteNoise à votre MIDDLEWAREvariable dans 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. Ensuite, modifiez votre wsgi.pyfichier comme expliqué dans la réponse de Johnny:

    #wsgi.py
    from django.core.wsgi import get_wsgi_application
    from whitenoise.django import DjangoWhiteNoise
    
    application = get_wsgi_application()
    application = DjangoWhiteNoise(application)
  4. Après cela, déployez vos modifications sur votre serveur (avec git ou tout ce que vous utilisez).

  5. Enfin, exécutez l' collectstaticoption depuis votre manage.pysur votre serveur. Cela copiera tous les fichiers de vos dossiers statiques dans le STATIC_ROOTrépertoire que nous avons spécifié auparavant:

    $ python manage.py collectstatic

    Vous verrez maintenant un nouveau dossier nommé staticfilesqui contient de tels éléments.

Après avoir suivi ces étapes, vous pouvez maintenant exécuter votre serveur et pourrez voir vos fichiers statiques en mode Production.

Mise à jour: Si vous aviez la version <4, le journal des modifications indique qu'il n'est plus nécessaire de déclarer le WSGI_APPLICATION = 'projectName.wsgi.application'dans votre settings.pyfichier.

DarkCygnus
la source
Je l'ai fait en conséquence, et lors du développement, il a bien fonctionné, mais pas en production. Vous rencontrez toujours le même problème lorsque DEBUG == False
Anna Huang
@AnnaHuang Qu'entendez-vous par développement et production? Avez-vous des environnements ou des machines distincts? Sont-ils configurés de la même manière?
DarkCygnus du
13

Vous pouvez réellement servir des fichiers statiques dans une application Django de production, en toute sécurité et sans DEBUG=True.

Plutôt que d'utiliser Django lui-même, utilisez dj_static dans votre fichier WSGI ( github ):

# 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
la source
2
J'ai depuis découvert le bruit blanc , qui peut être plus complet.
Robin Winslow
7

Ouvrez simplement votre projet urls.py, puis recherchez cette instruction if.

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

Vous pouvez modifier settings.DEBUG sur True et cela fonctionnera toujours. Mais si votre projet est quelque chose de sérieux, vous devriez penser aux autres solutions mentionnées ci-dessus.

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

Dans django 1.10, vous pouvez écrire ainsi:

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
la source
3
Votre code est correct, mais dans Django 1.10, la configuration est pour les médias et statique est: urlpatterns + = [url (r '^ media / (? P <path>. *) $', Serve, {'document_root': settings .MEDIA_ROOT,}), url (r '^ static / (? P <path>. *) $', Serve, {'document_root': settings.STATIC_ROOT}),]
Roberth Solís
6

Vous pouvez déboguer cela de différentes manières. Voici mon approche.

localsettings.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')} ),
    )

N'oubliez pas de lire les documents;)

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

Conrado
la source
0

La prise en charge des arguments d'affichage de chaîne pour url () est obsolète et sera supprimée dans Django 1.10

Ma solution est juste une petite correction à la solution Conrado ci-dessus.

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
la source
0

Bien que ce ne soit pas le plus sûr, mais vous pouvez changer le code source. aller versPython/2.7/site-packages/django/conf/urls/static.py

Modifiez ensuite comme suit:

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

Donc, si settings.debug==Falsecela n'affecte pas le code, essayez également python manage.py runserver --runserverd'exécuter des fichiers statiques après l'exécution .

REMARQUE : les informations ne doivent être utilisées qu'à des fins de test uniquement

Natuto
la source
0

J'ai apporté les modifications suivantes à mon projet / urls.py et cela a fonctionné pour moi

Ajoutez cette ligne: depuis django.conf.urls import url

et ajoutez: url (r '^ media / (? P. *) $', serve, {'document_root': settings.MEDIA_ROOT,}), dans urlpatterns.

Namrata Sharma
la source