为什么DEBUG = False设置会使django静态文件访问失败?


355

我正在使用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 2011年

具有测试服务器的本地计算机。我基本上想通过本地模拟场景(例如访问不存在的页面并导致运行时错误)来查看自定义错误处理的工作方式,但是我的静态内容无法加载。
nemesisfixx 2011年

可以在这里这样的服务器级别上完成,也可以通过添加urlpattern在Django级别上进行处理。我在下面的问题中发现了同样的问题。stackoverflow.com/questions/6405173/...
潘卡阿南德

Answers:


353

在关闭调试的情况下,Django将不再为您处理静态文件-生产Web服务器(Apache或其他服务器)应对此进行处理。


3
这实际上解决了我的好奇心,所以现在这很有意义,如果需要的话,我的确可以使用Apache来解决。我以为我自己的设置有问题。谢谢
nemesisfixx 2011年

5
我发现这个答案很有帮助。以防万一其他人处于我的情况下(将Google App Engine用于带有nonrel django的应用程序):别忘了更新app.yaml。
Lyndsey Ferguson

3
处理程序:-网址:/ static static_dir:静态
Lyndsey Ferguson

475

如果仍然需要在本地静态服务器(例如,在不调试的情况下进行测试),则可以在不安全模式下运行devserver:

manage.py runserver --insecure

6
尽管此标志有效,但它不提供collectstatic文件夹中的内容
Howie

5
太神奇了。谢谢您,先生,您是英雄。此答案应与接受的答案合并,因为它可以解决问题,而无需使用Django本身以外的其他方法提供静态服务。
Depado 2014年

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)

而且你很好走!

感谢车把创意博客

但是,实际上不建议在生产过程中以这种方式提供静态文件。您的生产Web服务器(如nginx)应该注意这一点。


1
听起来很有趣,但仅将那行添加到wgsi.py文件中对我来说不起作用。您链接的文档似乎还提供了有关使用WhiteNoise的其他说明。将尝试其他方法并在此处更新您。
DarkCygnus

+1,因为这最终导致了我的解决方案。我添加了一个答案,其中包括为使其真正起作用而采取的其他步骤。
DarkCygnus 18-4-18的

manage.py runserver --insecure没有为我工作。不过,这确实做到了。

3
请注意,在WhiteNoise版本4.0中,配置已更改。不要将这些行添加到wsgi.py。相反,只需添加'whitenoise.middleware.WhiteNoiseMiddleware'到中间件即可。请参见发行说明从更新日志
道格·哈里斯

为什么不推荐*?我已经在多个站点使用了多年,效果很好。甚至Heroku在其Django模板中也使用它。
奥马尔·冈萨雷斯

31

在urls.py中,我添加了以下行:

from django.views.static import serve 

在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无法加载吗?
Suchitha Deepal

是。唯一的作品!谢谢。
DrGeneral

真棒!不要忘记设置STATIC_ROOT和manage.py collectstatic。
DomingoR

2
如今替换url(re_path(
Leopd

19

如果在开发中使用静态服务视图,则必须具有DEBUG = True:

警告

仅当DEBUG为True时才有效。

那是因为这种观点非常低效并且可能不安全。这仅用于本地开发,决不能用于生产。

文件:在开发人员中提供静态档案

编辑:您可以添加一些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,我刚刚看到了。谢谢。

您可以将您的Web服务器设置为托管特定目录。通常,您会使用Apache或Nginx。Docs对此进行了介绍。
j_syk 2011年

谢谢@j_syk,我已经尝试过通过类似于您建议的其他一些非错误机制来查看404.html和500.html的方法。但是我想知道是否完全不可能像在生产中那样正确呈现页面,而仍然只在我的测试服务器上运行-当Debug关闭时,将静态文件处理委托给Apache为我解决了问题。感谢您的贡献。
nemesisfixx 2011年

@mcnemesis我不确定到底会发生什么,但是尝试设置TEMPLATE_DEBUG = False和DEBUG = True。如果您关闭了漂亮的错误,则不确定是否要使用404/500模板
j_syk

像预期的那样,这样做并没有产生任何积极的结果。
nemesisfixx 2011年

17

Johnny的回答很好,但仅添加其中描述的内容仍然对我不起作用。根据该答案,实际上对我有用的步骤包括:

  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本身,而是在WSGI文件(github)中使用dj_static

# 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,它可能功能更全。
罗宾·温斯洛

7

只需打开您的项目urls.py,然后找到此if语句即可。

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

您可以更改设置。在True上启用DEBUG,它将始终运行。但是,如果您的项目很严肃,那么您应该考虑上面提到的其他解决方案。

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 <path>。*)$',serve,{'document_root':settings.STATIC_ROOT}),]
罗伯特·索利斯


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

我对project / urls.py进行了以下更改,它对我有用

添加此行:从django.conf.urls导入url

并在urlpatterns中添加url(r'^ media /(?P。*)$',服务{{document_root':settings.MEDIA_ROOT,})。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.