ทำไม DEBUG = การตั้งค่าเท็จทำให้ django Static Files Access ของฉันล้มเหลว


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

สามารถทำได้ในระดับเซิร์ฟเวอร์เช่นที่นี่หรือสามารถจัดการที่ระดับ Django โดยเพิ่ม urlpattern ฉันพบคำถามด้านล่างนี้สำหรับปัญหาเดียวกัน stackoverflow.com/questions/6405173/…
Pankaj Anand

คำตอบ:


353

ด้วยการดีบักการปิด Django จะไม่จัดการกับไฟล์คงที่สำหรับคุณอีกต่อไป - เว็บเซิร์ฟเวอร์การผลิต (Apache หรือบางอย่าง) ควรดูแลสิ่งนั้น


3
นี่ทำให้ฉันอยากรู้อยากเห็นจริง ๆ แล้วตอนนี้มันสมเหตุสมผลแล้วและฉันก็สามารถดูแลกับ Apache ได้ถ้าต้องการ ฉันคิดว่ามันเป็นปัญหากับการตั้งค่าของฉันเอง ขอบคุณ
nemesisfixx

5
ฉันพบว่าคำตอบนี้มีประโยชน์มาก ในกรณีที่คนอื่นอยู่ในสถานการณ์เดียวกันของฉัน (ใช้ Google App Engine สำหรับแอพที่ไม่มี django): อย่าลืมอัปเดตแอป yaml
Lyndsey Ferguson

3
ตัวจัดการ: - url: / static static_dir: static
Lyndsey Ferguson

475

หากคุณยังคงต้องเซิร์ฟเวอร์คงที่ภายในเครื่อง (เช่นสำหรับการทดสอบโดยไม่มีการดีบัก) คุณสามารถเรียกใช้ devserver ในโหมดที่ไม่ปลอดภัย:

manage.py runserver --insecure

6
ในขณะที่การตั้งค่าสถานะนี้ใช้งานไม่ได้ให้บริการเนื้อหาจากโฟลเดอร์สะสม
Howie

5
นั่นคือเวทมนตร์ ขอบคุณครับคุณเป็นฮีโร่ คำตอบนี้ควรถูกรวมเข้ากับคำตอบที่ได้รับการยอมรับเนื่องจากมันสามารถแก้ปัญหาได้โดยไม่ต้องให้บริการคงที่โดยใช้วิธีอื่นนอกเหนือจาก django
Depado

1
นี่คือทั้งหมดที่ฉันต้องการ แม้ว่าแนวปฏิบัติที่ดีที่สุดคือการใช้ตัวแปรสภาพแวดล้อมเพื่อแยกความแตกต่างระหว่างการพัฒนาและสภาพแวดล้อมการผลิตกับการสลับแก้จุดบกพร่อง
Neeraj Gupta

1
โปรดทราบ: นั่นจะไม่ทำงานกับ ManifestStaticFilesStorage ในฐานะcode.djangoproject.com/ticket/19295
Andrea Rabbaglietti

9
บางคนสามารถบอกฉันได้ว่าสิ่งที่ไม่ปลอดภัยเกี่ยวกับเรื่องนี้คืออะไร
Kavi Vaidya

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)

และคุณก็พร้อมที่จะไป!

เครดิตบล็อก Handlebar สร้างสรรค์

แต่ไม่แนะนำให้ใช้ไฟล์แบบคงที่ในการผลิต เว็บเซิร์ฟเวอร์ที่ใช้งานจริงของคุณ (เช่น 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 ก็ใช้มันในเทมเพลต Django ของพวกเขา
Omar Gonzalez

33

ใน URL ฉันเพิ่มบรรทัดนี้:

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 admin แผงไม่โหลด?
ดังนี้ดังนั้น Deepal

ใช่. คนเดียวที่ทำงาน !! ขอบคุณ
DrGeneral

น่ากลัว! อย่าลืมตั้งค่า STATIC_ROOT และ Manage.py สะสม
DomingoR

2
ปัจจุบันแทนที่url(ด้วยre_path(
Leopd

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 ผ่านกลไกอื่นที่ไม่ใช่ข้อผิดพลาดคล้ายกับที่คุณแนะนำ แต่ฉันอยากรู้ว่ามันเป็นไปไม่ได้เลยที่จะให้หน้าของฉันแสดงผลอย่างถูกต้องตามที่พวกเขาต้องการในการผลิตหรือไม่ในขณะที่ยังคงทำงานบนเซิร์ฟเวอร์ทดสอบของฉันอยู่เท่านั้น ขอบคุณสำหรับการมีส่วนร่วม
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ไฟล์ของคุณตามที่อธิบายไว้ในคำตอบของ Johnny:

    #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
Anna Huang

@ 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
ฉันได้ค้นพบwhitenoiseซึ่งอาจมีคุณสมบัติครบถ้วนมากกว่านี้
Robin Winslow

7

เพียงเปิด urls.py โครงการของคุณจากนั้นค้นหาคำสั่ง if

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 '^ สื่อ / (? P <path>. *) $', การบริการ, {'document_root': การตั้งค่า .MEDIA_ROOT,}), url (r '^ static / (? P <path>. *) $', ให้บริการ, {'document_root': settings.STATIC_ROOT}),]
Roberth Solís

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

โซลูชันของฉันเป็นเพียงการแก้ไขเล็กน้อยสำหรับโซลูชัน 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

แม้ว่ามันจะไม่ปลอดภัย แต่คุณสามารถเปลี่ยนได้ในซอร์สโค้ด นำทางไปยัง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 ของฉันและมันก็ใช้ได้ผลสำหรับฉัน

เพิ่มบรรทัดนี้: จาก django.conf.urls นำเข้า url

และเพิ่ม: url (r '^ media / (? P. *) $', ให้บริการ, {'document_root': settings.MEDIA_ROOT,}), ใน urlpatterns

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.