Dlaczego DEBUG = Fałszywe ustawienie powoduje awarię dostępu do plików statycznych django?


356

Buduję aplikację, używając Django jako mojego konia roboczego. Do tej pory wszystko było dobrze - określone ustawienia db, skonfigurowane katalogi statyczne, adresy URL, widoki itp. Ale problemy zaczęły się pojawiać w momencie, gdy chciałem wyrenderować własne piękne i niestandardowe strony 404.html i 500.html.

Przeczytałem dokumenty na temat niestandardowej obsługi błędów i ustawiłem niezbędne konfiguracje w UrlsConf, utworzyłem odpowiednie widoki i dodałem pliki 404.html i 500.html do katalogu szablonów mojej aplikacji (również określonego w pliku settings.py).

Ale doktorzy mówią you can actually view custom error views until Debug is Off, więc wyłączyłem to, aby przetestować swoje rzeczy, i to wtedy rzeczy szaleją!

Nie tylko nie mogę wyświetlić niestandardowego pliku 404.html (w rzeczywistości ładuje się, ale ponieważ każda z moich stron błędów zawiera graficzny komunikat o błędzie - jak jakiś fajny obraz), źródło strony błędów ładuje się, ale nic innego się nie ładuje! Nawet niepowiązany CSS lub JavaScript!

Zasadniczo po ustawieniu DEBUG = Falsewszystkie widoki zostaną załadowane, ale żadna powiązana treść (CSS, JavaScript, obrazy itp.) Nie będzie ładowana! Co się dzieje? Czy czegoś brakuje w odniesieniu do plików statycznych i DEBUGustawień?


Jak się masz? Komputer lokalny z serwerem testowym?
— j_syk

komputer lokalny z serwerem testowym. Zasadniczo chcę zobaczyć, jak działałaby moja niestandardowa obsługa błędów, lokalnie symulując scenariusze, takie jak uzyskiwanie dostępu do nieistniejących stron i powodowanie błędów w czasie wykonywania - ale moja zawartość statyczna nie ładuje się.
— nemesisfixx

Albo można to zrobić na poziomie serwera, jak tutaj, lub można to zrobić na poziomie Django, dodając urlpattern. Znalazłem to poniższe pytanie dotyczące tego samego problemu. stackoverflow.com/questions/6405173/…
— Pankaj Anand

Odpowiedzi:


353

Po wyłączeniu debugowania Django nie będzie już obsługiwał plików statycznych - produkcyjny serwer WWW (Apache lub coś takiego) powinien się tym zająć.


3
To faktycznie uspokaja moją ciekawość, więc teraz ma to sens i rzeczywiście mogę zająć się tym z Apache, jeśli zajdzie taka potrzeba. Myślałem, że to problem z moimi własnymi ustawieniami. Dzięki
— nemesisfixx

5
Ta odpowiedź była dla mnie bardzo pomocna. Na wypadek, gdyby ktoś był w tej samej sytuacji (używając Google App Engine dla aplikacji z nonrel django): nie zapomnij zaktualizować app.yaml.
— Lyndsey Ferguson,

3
handlers: - url: / static static_dir: static
— Lyndsey Ferguson

475

Jeśli nadal potrzebujesz lokalnego serwera statycznego (np. Do testowania bez debugowania), możesz uruchomić devserver w trybie niepewnym:

manage.py runserver --insecure

6
Chociaż ta flaga działa, nie wyświetla treści z folderu kolekcjonerskiego
— Howie

5
To magia. Dziękuję panu, jesteś bohaterem. Ta odpowiedź powinna zostać połączona z odpowiedzią zaakceptowaną, ponieważ rozwiązuje problem bez konieczności podawania statycznego za pomocą innego sposobu niż sam django.
— Depado

1
To było wszystko, czego potrzebowałem. Chociaż najlepszą praktyką byłoby użycie zmiennej środowiskowej do rozróżnienia między środowiskiem programistycznym i produkcyjnym oraz przełączania debugowania.
— Neeraj Gupta

1
Uwaga: to NIE będzie działać z ManifestStaticFilesStorage jako code.djangoproject.com/ticket/19295
— Andrea Rabbaglietti

9
czy ktoś może mi powiedzieć, co jest w tym takiego niepewnego
— Kavi Vaidya,

36

Możesz użyć WhiteNoise do obsługi plików statycznych w produkcji.

Zainstalować:

pip install WhiteNoise

I zmień plik wsgi.py na:

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

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

I możesz iść!

Kredyt na blogu Creative Handlebar .

ALE tak naprawdę nie zaleca się serwowania plików statycznych w ten sposób podczas produkcji. Twój produkcyjny serwer internetowy (jak nginx) powinien się tym zająć.


1
Brzmi interesująco, ale nie działało dla mnie, po prostu dodając tę ​​linię do wgsi.pypliku. Dokumentacja, którą dowiązałeś, wydaje się zawierać inne instrukcje dotyczące korzystania z WhiteNoise. Spróbuję innych sposobów i zaktualizuję cię tutaj.
— DarkCygnus,

+1, ponieważ to ostatecznie doprowadziło mnie do rozwiązania. Dodałem odpowiedź, w której zawarłem dodatkowe kroki, które podjąłem, aby faktycznie to działało.
— DarkCygnus,

manage.py runserver --insecurenie działało dla mnie. Ten jednak ma.
— Jee

3
Pamiętaj, że w wersji 4.0 WhiteNoise konfiguracja uległa zmianie. Nie dodawaj tych wierszy do pliku wsgi.py. Zamiast tego po prostu dodaj 'whitenoise.middleware.WhiteNoiseMiddleware'do oprogramowania pośredniego. Zobacz informacje o wydaniu dziennika zmian
— Doug Harris

Dlaczego * nie jest zalecane? Używam go od lat w kilku witrynach, działa świetnie. Nawet Heroku używa go w szablonie Django.
— Omar Gonzalez

33

W urls.py dodałem tę linię:

from django.views.static import serve 

dodaj te dwa adresy URL w urlpatterns:

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

a zarówno statyczne, jak i multimedialne pliki były dostępne, gdy DEBUG = FAŁSZ.
Mam nadzieję, że to pomoże :)


Po zakończeniu css panel administracyjny nie ładuje się ??
— Takitha Deepal

Tak. Jedyny, który działa !! dzięki.
— DrGeneral

NIESAMOWITE! Nie zapomnij ustawić STATIC_ROOT i manage.py collectstatic.
— DomingoR,

2
Obecnie wymienić url(zre_path(
— Leopd

19

Jeśli używasz statycznego widoku udostępniania w fazie projektowania, musisz mieć DEBUG = True:

Ostrzeżenie

Działa to tylko wtedy, gdy DEBUG jest Prawdą.

Jest tak, ponieważ ten pogląd jest rażąco nieefektywny i prawdopodobnie niepewny. Jest to przeznaczone wyłącznie na rozwój lokalny i nigdy nie powinno być wykorzystywane w produkcji.

Dokumenty: serwowanie plików statycznych w programistyce

EDYCJA: Możesz dodać kilka adresów URL tylko w celu przetestowania szablonów 404 i 500, po prostu użyj ogólnego widoku direct_to_template w swoich adresach URL.

from django.views.generic.simple import direct_to_template

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

1
W jaki sposób można następnie obsłużyć pliki statyczne podczas produkcji? NVM, właśnie to widziałem. Dzięki.

skonfigurowałbyś swój serwer WWW do obsługi określonego katalogu. Najczęściej będziesz używać Apache lub Nginx. Dokumenty trochę w to zagłębiają.
— j_syk

dzięki @j_syk, już wypróbowałem to podejście do przeglądania 404.html i 500.html za pomocą innego mechanizmu niezwiązanego z błędami podobnego do tego, co sugerujesz. Chciałem jednak wiedzieć, czy nie jest możliwe, aby moje strony renderowały się poprawnie tak, jak w środowisku produkcyjnym, a jednocześnie działały tylko na moim serwerze testowym - delegowanie obsługi plików statycznych do Apache, gdy Debugowanie jest wyłączone, rozwiązuje to dla mnie. Dziękuję za pomoc.
— nemesisfixx

@mcnemesis Nie jestem pewien, co się stanie, ale spróbuj ustawić TEMPLATE_DEBUG = Fałsz, a DEBUG = Prawda. Jeśli wyłączysz ładne błędy, nie jestem pewien, czy zamiast tego trafi do szablonów
— 404/500

zgodnie z oczekiwaniami, zrobienie tego nie przyniosło żadnych pozytywnych rezultatów, ale wciąż dzięki.
— nemesisfixx

17

Odpowiedź Johnny'ego jest świetna, ale nadal nie działała dla mnie po prostu poprzez dodanie linii tam opisanych. W oparciu o tę odpowiedź kroki, które faktycznie dla mnie zadziałały, gdzie:

  1. Zainstaluj WhiteNoise zgodnie z opisem:

    pip install WhiteNoise
  2. Utwórz STATIC_ROOTzmienną i dodaj WhiteNoise do swojej MIDDLEWAREzmiennej w 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. Następnie zmodyfikuj wsgi.pyplik zgodnie z wyjaśnieniem w odpowiedzi Johnny'ego:

    #wsgi.py
    from django.core.wsgi import get_wsgi_application
    from whitenoise.django import DjangoWhiteNoise
    
    application = get_wsgi_application()
    application = DjangoWhiteNoise(application)
  4. Następnie wdróż zmiany na serwerze (za pomocą git lub cokolwiek, którego używasz).

  5. Na koniec uruchom tę collectstaticopcję manage.pyna swoim serwerze. Spowoduje to skopiowanie wszystkich plików z folderów statycznych do STATIC_ROOTokreślonego wcześniej katalogu:

    $ python manage.py collectstatic

    Zobaczysz teraz nowy folder o nazwie staticfileszawierającej takie elementy.

Po wykonaniu tych kroków możesz teraz uruchomić swój serwer i będziesz mógł zobaczyć swoje pliki statyczne w trybie produkcyjnym.

Aktualizacja: W przypadku, gdy miał wersję <4 changelog wskazuje, że nie jest już konieczne, aby zadeklarować WSGI_APPLICATION = 'projectName.wsgi.application'na settings.pypliku.


Zrobiłem to odpowiednio i przy rozwoju działało dobrze, ale nie w produkcji. Nadal mam ten sam problem, gdy DEBUG == False
— Anna Huang

@AnnaHuang Co rozumiesz przez rozwój i produkcję? Czy masz oddzielne środowiska lub maszyny? Czy są skonfigurowane w ten sam sposób?
— DarkCygnus,

13

W rzeczywistości możesz obsługiwać pliki statyczne w produkcyjnej aplikacji Django, bezpiecznie i bez DEBUG=True .

Zamiast używać samego Django, użyj dj_static w pliku 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
Od tego czasu odkryłem whitenoise , który może być bardziej w pełni funkcjonalny.
— Robin Winslow,

7

Po prostu otwórz projekt urls.py, a następnie znajdź tę instrukcję if.

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

Możesz zmienić ustawienia. DEBUG na True i zawsze będzie działać. Ale jeśli twój projekt jest czymś poważnym, powinieneś pomyśleć o innych rozwiązaniach wymienionych powyżej.

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

W django 1.10 możesz napisać:

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

3
Twój kod jest poprawny, ale w Django 1.10 konfiguracja jest dla mediów, a statyczna to: urlpatterns + = [url (r '^ media / (? P <ścieżka>. *) $', Serw, {'document_root': ustawienia .MEDIA_ROOT,}), url (r '^ static / (? P <path>. *) $', Służyć, {'document_root': settings.STATIC_ROOT}),]
— Roberth Solís


0

Obsługa argumentów widoku łańcucha dla url () jest przestarzała i zostanie usunięta w Django 1.10

Moje rozwiązanie to tylko niewielka korekta powyższego rozwiązania Conrado.

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

Chociaż nie jest to najbezpieczniejsze, ale możesz zmienić kod źródłowy. nawigować doPython/2.7/site-packages/django/conf/urls/static.py

Następnie edytuj w następujący sposób:

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

Więc jeśli settings.debug==Falsenie wpłynie to na kod, również po uruchomieniu spróbujpython manage.py runserver --runserver uruchomić pliki statyczne.

UWAGA : Informacje należy wykorzystywać wyłącznie do testowania


0

Wprowadziłem następujące zmiany w moim projekcie / urls.py i zadziałało to dla mnie

Dodaj tę linię: z adresu importu django.conf.urls

i dodaj: url (r '^ media / (? P. *) $', obsłuż, {'document_root': settings.MEDIA_ROOT,}), w urlpatterns.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.