Почему установка 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настроек?

nemesisfixx
источник
Как вы хостинг? Локальная машина с тестовым сервером?
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.
Надеюсь, поможет :)

stathoula
источник
Когда это сделано админ панель 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'})
)
j_syk
источник
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файле.

DarkCygnus
источник
Я сделал это соответственно, и в процессе разработки он работал нормально, но не в производстве. Все еще есть та же проблема, когда 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

Conrado
источник
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')} ),
        )
be_good_do_good
источник
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запустить статические файлы.

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

Natuto
источник
0

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

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

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

Намрата Шарма
источник