Чому DEBUG = Неправильне налаштування робить невдалим доступ до статичних файлів мого django?


356

Я будую додаток, використовуючи Django в якості моєї робочої коні. На сьогодні все добре - задані налаштування db, налаштовані статичні каталоги, 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

Або це можна зробити на рівні сервера, як тут, або з ним можна обробити на рівні Джанго, додавши urlpattern. Я знайшов це нижче питання для тієї ж проблеми. stackoverflow.com/questions/6405173/…
Панкай Ананд

Відповіді:


353

При відключенні налагодження Django більше не обробляє статичні файли для вас - про це повинен подбати ваш виробничий веб-сервер (Apache або щось подібне).


3
Це насправді вгамовує мою цікавість, тож тепер це має сенс, і я справді можу подбати про це з Apache, якщо буде потреба. Я вважав, що це проблема з моїми власними налаштуваннями. Спасибі
nemesisfixx

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

3
обробники: - url: / static static_dir: static
Lyndsey Ferguson

475

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

manage.py runserver --insecure

6
Поки цей прапор працює, він не подає вміст з колекції
папників collestatic

5
Це магія. Дякую, сер, ви герой. Цю відповідь слід об'єднати з прийнятою відповіддю, оскільки вона вирішує проблему, не потребуючи подання статики, використовуючи інший спосіб, ніж сам джанго.
Депадо

1
Це все, що мені було потрібно. Хоча найкращою практикою було б використання змінної середовища для розмежування між розвитком та виробничим середовищем та перемиканням налагодження.
Neeraj Gupta

1
Зверніть увагу: це НЕ буде працювати з ManifestStaticFilesStorage як code.djangoproject.com/ticket/19295
Andrea Rabbaglietti

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не працювало для мене. Цей, хоча.
Jee

3
Зауважте, що з випуском WhiteNoise 4.0 конфігурація змінилася. Не додайте ці рядки до wsgi.py. Натомість просто додайте 'whitenoise.middleware.WhiteNoiseMiddleware'до середнього програмного забезпечення. Дивіться примітки до випуску із
Doug Harris

Чому * не рекомендується? Я його використовую роками на кількох сайтах, чудово працює. Навіть Heroku використовує це у своєму шаблоні Джанго.
Омар Гонсалес

33

У urls.py я додав цей рядок:

from django.views.static import serve 

додайте ці два URL-адреси в URL-адреси:

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 панелі адміністратора не завантажується ??
Сукіта Діпал

Так. Єдиний, хто працює !! Дякую.
DrGeneral

ДУЖЕ! Не забудьте встановити STATIC_ROOT та manage.py collestatic.
DomingoR

2
Нині замінимо url(наre_path(
Леопд

19

Якщо ви використовуєте статичний подання сервісу в розробці, вам потрібно мати DEBUG = True:

Увага

Це буде працювати лише в тому випадку, коли DEBUG є True.

Це тому, що ця думка є надзвичайно неефективною і, ймовірно, небезпечною. Це призначено лише для місцевого розвитку, і його ніколи не слід використовувати у виробництві.

Документи: подання статичних файлів у програмі

EDIT: Ви можете додати деякі URL-адреси просто для тестування шаблонів 404 та 500, просто використовуйте у своїх URL-адресах загальний вигляд direct_to_template.

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, коли Debug Off Off, це вирішує для мене. Дякуємо за ваш внесок.
nemesisfixx

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

як очікувалося, це не дало позитивних результатів. Але все ж дякую.
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 == False
Анна Хуанг

@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 settings.DEBUG:
    urlpatterns += patterns(
        'django.views.static',
        (r'^media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )

Ви можете змінити налаштування.DEBUG на 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 '^ статичний / (? P <шлях>. *) $',
Виконувати

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,}), в URL-адресах.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.