Почему установка DEBUG = False приводит к сбою доступа к моим статическим файлам в django?


356

Я создаю приложение, используя Django в качестве моей рабочей лошадки. До сих пор все было хорошо - заданные настройки БД, настроенные статические каталоги, URL-адреса, представления и т. Д. Но проблемы начали красться в тот момент, когда я захотел отрисовать свои собственные красивые и собственные страницы 404.html и 500.html.

Я прочитал документы по пользовательской обработке ошибок и установил необходимые конфигурации в UrlsConf, создал соответствующие представления и добавил 404.html и 500.html в каталог шаблонов моего приложения (также указанный в settings.py).

Но в документах сказано you can actually view custom error views until Debug is Off, так что я отключил его, чтобы проверить свои материалы, и вот тут-то и началось безумство!

Я не только не могу просмотреть пользовательский файл 404.html (на самом деле он загружается, но и потому, что каждая из моих страниц с ошибками содержит графическое сообщение об ошибке - как хорошее изображение), источник страницы ошибок загружается, но больше ничего не загружается! Даже не связанные CSS или Javascript!

Как правило, после установки DEBUG = Falseзагружаются все представления, но любой связанный контент (CSS, Javascript, Изображения и т. Д.) Не загружается! Что происходит? Чего-то не хватает в отношении статических файлов и DEBUGнастроек?


Как вы хостинг? Локальная машина с тестовым сервером?
— j_syk

локальная машина с тестовым сервером. Я в основном хочу посмотреть, как моя пользовательская обработка ошибок будет работать, локально моделируя сценарии, такие как доступ к несуществующим страницам и вызывая ошибки во время выполнения - но мой статический контент не загружается.
— nemesisfixx

Либо это можно сделать на уровне сервера, как здесь, либо это можно сделать на уровне Django, добавив urlpattern. Я нашел этот вопрос ниже для той же проблемы. stackoverflow.com/questions/6405173/…
— Панкадж Ананд

Ответы:


353

С отключенной отладкой Django больше не будет обрабатывать статические файлы для вас - ваш рабочий веб-сервер (Apache или что-то еще) должен позаботиться об этом.


3
Это фактически решает мое любопытство, так что теперь это имеет смысл, и я действительно могу позаботиться об этом с Apache, если это будет необходимо. Я думал, что это была проблема с моими собственными настройками. Спасибо
— nemesisfixx

5
Я нашел этот ответ очень полезным. На всякий случай, если кто-то еще находится в моей ситуации (используя Google App Engine для приложения с nonrel django): не забудьте обновить app.yaml.
— Линдси Фергюсон

3
обработчики: - url: / static static_dir: static
— Линдси Фергюсон

476

Если вам все еще нужно локально настроить статический сервер (например, для тестирования без отладки), вы можете запустить devserver в небезопасном режиме:

manage.py runserver --insecure

6
Хотя этот флаг работает, он не обслуживает содержимое из папки collectstatic
— Howie

5
Это волшебство. Спасибо, сэр, вы герой. Этот ответ должен быть объединен с принятым ответом, поскольку он решает проблему, не прибегая к статической обработке другим способом, чем сам django.
— Депадо

1
Это было все, что мне было нужно. Хотя лучше всего использовать переменную среды, чтобы различать среду разработки и производства и переключение отладки.
— Нирадж Гупта

1
Обратите внимание: это не будет работать с ManifestStaticFilesStorage как code.djangoproject.com/ticket/19295
— Андреа Раббаглиетти

9
может кто-нибудь сказать мне, что такого опасного в этом
— Кави Вайдья

36

Вы можете использовать WhiteNoise для обслуживания статических файлов в производстве.

Установка:

pip install WhiteNoise

И измените ваш файл wsgi.py на это:

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

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

И ты в порядке!

Кредит на Руль Творческий Блог .

НО, действительно, не рекомендуется обслуживать статические файлы таким способом в производстве. Ваш производственный веб-сервер (например, nginx) должен позаботиться об этом.


1
Звучит интересно, но у меня не получилось, просто добавив эту строку в wgsi.pyфайл. Документация, на которую вы ссылаетесь, похоже, содержит другие инструкции по использованию WhiteNoise Попробую другие способы и обновлю вас здесь.
— DarkCygnus

+1, как это было то, что в конечном итоге привело меня к решению. Я добавил ответ, где я включил дополнительные шаги, которые я предпринял, чтобы заставить его работать.
— DarkCygnus

manage.py runserver --insecureне работал для меня Этот делает, хотя.
— Джи

3
Обратите внимание, что в WhiteNoise версии 4.0 конфигурация изменилась. Не добавляйте эти строки в wsgi.py. Вместо этого просто добавьте 'whitenoise.middleware.WhiteNoiseMiddleware'промежуточное ПО. См. Примечания к выпуску из
— Даг Харрис

Почему * не рекомендуется? Я использую его годами на нескольких сайтах, прекрасно работает. Даже Heroku использует его в своем шаблоне Django.
— Омар Гонсалес

33

В urls.py я добавил эту строку:

from django.views.static import serve 

Добавьте эти два URL в urlpatterns:

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

и статические, и мультимедийные файлы были доступны, когда DEBUG = FALSE.
Надеюсь, поможет :)


Когда это сделано админ панель css не загружается ??
— Тузита Дипал

Да. Единственный, который работает! Спасибо.
— Генеральный директор

КЛАССНО! Не забудьте установить STATIC_ROOT и manage.py collectstatic.
— ДомингоР

2
В настоящее время заменить url(наre_path(
— Леопд

19

Если вы используете статическое представление подачи в разработке, вы должны иметь DEBUG = True:

Предупреждение

Это будет работать, только если DEBUG - True.

Это потому, что эта точка зрения крайне неэффективна и, вероятно, небезопасна. Это предназначено только для местного развития и никогда не должно использоваться в производстве.

Документы: обслуживание статических файлов в разработке

РЕДАКТИРОВАТЬ: Вы можете добавить некоторые URL-адреса только для проверки ваших 404 и 500 шаблонов, просто используйте общий вид direct_to_template в ваших URL-адресах.

from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
    ('^404testing/$', direct_to_template, {'template': '404.html'})
)

1
Как один, а затем обслуживать статические файлы на производстве? NVM, я только что видел это. Спасибо.

Вы должны настроить свой веб-сервер для размещения определенного каталога. Чаще всего вы используете Apache или Nginx. Документы идут в это немного.
— j_syk

спасибо @j_syk, я уже пробовал этот подход просмотра 404.html и 500.html через какой-то другой механизм без ошибок, подобный тому, что вы предлагаете. Но я хотел знать, было ли абсолютно невозможно, чтобы мои страницы правильно отображались так, как они бы работали, хотя они все еще просто работали на моем тестовом сервере - делегирование статической обработки файлов в Apache при выключенной отладке решает эту проблему. Спасибо за помощь.
— nemesisfixx

@mcnemesis Я не уверен, что именно произойдет, но попробуйте установить TEMPLATE_DEBUG = False и DEBUG = True. Если вы отключите симпатичные ошибки, я не уверен, что вместо этого они перейдут на шаблоны
— 404/500

Как и ожидалось, это не дало никаких положительных результатов. Но все равно спасибо.
— nemesisfixx

17

Ответ Джонни великолепен, но он все равно не сработал, просто добавив описанные там строки. Исходя из этого ответа, шаги, которые на самом деле работали для меня, где:

  1. Установите WhiteNoise, как описано:

    pip install WhiteNoise
  2. Создайте STATIC_ROOTпеременную и добавьте WhiteNoise к вашей MIDDLEWAREпеременной в 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. Затем измените wsgi.pyфайл, как описано в ответе Джонни:

    #wsgi.py
    from django.core.wsgi import get_wsgi_application
    from whitenoise.django import DjangoWhiteNoise
    
    application = get_wsgi_application()
    application = DjangoWhiteNoise(application)
  4. После этого разверните свои изменения на своем сервере (с помощью git или чего-либо еще).

  5. Наконец, запустите collectstaticопцию manage.pyна вашем сервере. Это скопирует все файлы из ваших статических папок в STATIC_ROOTкаталог, который мы указали ранее:

    $ python manage.py collectstatic

    Теперь вы увидите новую папку с staticfilesтакими элементами.

Выполнив следующие действия, вы теперь можете запустить свой сервер и сможете видеть ваши статические файлы в режиме производства.

Обновление: если у вас версия <4, журнал изменений показывает, что больше нет необходимости объявлять файл в WSGI_APPLICATION = 'projectName.wsgi.application'вашем settings.pyфайле.


Я сделал это соответственно, и в процессе разработки он работал нормально, но не в производстве. Все еще есть та же проблема, когда DEBUG == Ложь
— Анна Хуан

@AnnaHuang Что вы подразумеваете под разработкой и производством? У вас есть отдельные среды или машины? Они настроены одинаково?
— DarkCygnus

13

На самом деле вы можете работать со статическими файлами в рабочем приложении Django безопасно и без DEBUG=True .

Вместо использования самого Django, используйте dj_static в вашем файле 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())

2
С тех пор я обнаружил белый шум , который может быть более полнофункциональным.
— Робин Уинслоу

7

Просто откройте свой проект urls.py, а затем найдите выражение if.

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

Вы можете изменить настройки. Отладка на True, и она будет работать всегда. Но если у вас серьезный проект, подумайте о других решениях, упомянутых выше.

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

В Django 1.10 вы можете написать так:

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

3
Ваш код правильный, но в Django 1.10 конфигурация для носителей и статических: urlpatterns + = [url (r '^ media / (? P <path>. *) $', Serve, {'document_root': settings .MEDIA_ROOT,}), url (r '^ static / (? P <путь>. *) $', Serve, {'document_root': settings.STATIC_ROOT}),]
— Роберт Сольс

6

Вы можете отладить это разными способами. Вот мой подход.

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

Обязательно прочитайте документы;)

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


0

Поддержка аргументов строкового представления для url () устарела и будет удалена в Django 1.10

Мое решение - просто небольшая поправка к решению Конрадо выше.

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

0

Хотя это не безопасно, но вы можете изменить в исходном коде. перейдите кPython/2.7/site-packages/django/conf/urls/static.py

Затем отредактируйте следующим образом:

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

Итак, если settings.debug==Falseэто не повлияет на код, также после запуска попробуйте python manage.py runserver --runserverзапустить статические файлы.

ПРИМЕЧАНИЕ : информация должна использоваться только для тестирования


0

Я внес следующие изменения в свой проект / urls.py, и он работал на меня

Добавьте эту строку: из URL импорта django.conf.urls

и добавьте: url (r '^ media / (? P. *) $', serve, {'document_root': settings.MEDIA_ROOT,}) в urlpatterns.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.