为啥 DEBUG=False 设置使我的 django 静态文件访问失败?

Posted

技术标签:

【中文标题】为啥 DEBUG=False 设置使我的 django 静态文件访问失败?【英文标题】:Why does DEBUG=False setting make my django Static Files Access fail?为什么 DEBUG=False 设置使我的 django 静态文件访问失败? 【发布时间】:2011-08-15 18:04:05 【问题描述】:

我正在使用 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 设置是否缺少某些内容?

【问题讨论】:

您的托管情况如何?带有测试服务器的本地机器? 带有测试服务器的本地机器。我基本上想通过本地模拟场景(例如访问不存在的页面和导致运行时错误)来了解我的自定义错误处理如何工作 - 但我的静态内容不会加载。 可以像这里一样在服务器级别完成,也可以通过添加 urlpattern 在 Django 级别处理。我在下面的问题中发现了同样的问题。 ***.com/questions/6405173/… 【参考方案1】:

如果您仍需要在本地提供静态服务器(例如,无需调试即可进行测试),您可以在不安全模式下运行 devserver:

manage.py runserver --insecure

【讨论】:

虽然此标志有效,但它不提供来自 collectstatic 文件夹的内容 这很神奇。谢谢楼主,你是英雄。这个答案应该与接受的答案合并,因为它可以解决问题,而不必使用 django 本身以外的其他方式提供静态服务。 这就是我所需要的。尽管最佳做法是使用环境变量来区分开发和生产环境以及调试切换。 有人可以告诉我这有什么不安全的地方 @KaviVaidya - 它只是不安全的,因为它没有经过仔细检查以确保它是安全的。有关详细信息,请参阅***.com/a/31097709/303056。恕我直言,这是一个非常糟糕的命名选择,将关于安全性的 FUD 与明显的性能限制混为一谈。【参考方案2】:

关闭调试后,Django 将不再为您处理静态文件 - 您的生产网络服务器(Apache 或其他东西)应该负责处理。

【讨论】:

这实际上解决了我的好奇心,所以现在它是有道理的,如果需要的话,我确实可以使用 Apache 来处理它。我还以为是我自己设置的问题。谢谢 我发现这个答案很有帮助。以防万一其他人处于我同样的情况(使用 Google App Engine 和 nonrel django 的应用程序):不要忘记更新 app.yaml。 handlers: - url: /static static_dir: static 对我来说没有意义。我想用 Debug=False 以某种方式在本地测试它 manage.py runserver --insecure 用于使用 debug=True 提供静态文件【参考方案3】:

在 urls.py 我添加了这一行:

from django.views.static import serve 

在 urlpatterns 中添加这两个 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 时,静态文件和媒体文件都可以访问。 希望对你有帮助:)

【讨论】:

太棒了!不要忘记设置 STATIC_ROOT 和 manage.py collectstatic。 现在用re_path(替换url(【参考方案4】:

您可以使用WhiteNoise 在生产环境中提供静态文件。

安装:

pip install WhiteNoise==2.0.6

并将您的 wsgi.py 文件更改为:

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

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

你很高兴!

归功于Handlebar Creative Blog。

但是,真的不建议在生产中以这种方式提供静态文件。您的生产网络服务器(如 nginx)应该负责。

【讨论】:

听起来很有趣,但对我来说只是将那一行添加到wgsi.py 文件中并没有用。您链接的文档似乎提供了使用 WhiteNoise 的其他说明。将尝试其他方式并在此处更新您。 +1 因为这是最终导致我找到解决方案的原因。我添加了一个answer,其中包含了我为使其实际工作而采取的其他步骤。 manage.py runserver --insecure 对我不起作用。不过,这个可以。 请注意,在 WhiteNoise 4.0 版中,配置发生了变化。不要将这些行添加到 wsgi.py。相反,只需将 'whitenoise.middleware.WhiteNoiseMiddleware' 添加到中间件即可。请参阅更新日志中的release notes 为什么不推荐*?我已经在几个网站上使用它多年了,效果很好。甚至 Heroku 在他们的 Django 模板中也使用了它。【参考方案5】:

Johnny 的answer 很棒,但仅仅通过添加那里描述的那些行仍然对我不起作用。根据该答案,实际对我有用的步骤在哪里:

    按照说明安装WhiteNoise:

    pip install WhiteNoise
    

    创建STATIC_ROOT 变量并将WhiteNoise 添加到settings.py 中的MIDDLEWARE 变量:

    #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
    

    然后,按照 Johnny 的回答中的说明修改您的 wsgi.py 文件:

    #wsgi.py
    from django.core.wsgi import get_wsgi_application
    from whitenoise.django import DjangoWhiteNoise
    
    application = get_wsgi_application()
    application = DjangoWhiteNoise(application)
    

    之后,将您的更改部署到您的服务器(使用 git 或您使用的任何工具)。

    最后,从您的服务器上的manage.py 运行collectstatic 选项。这会将静态文件夹中的所有文件复制到我们之前指定的STATIC_ROOT 目录中:

    $ python manage.py collectstatic
    

    您现在将看到一个名为 staticfiles 的新文件夹,其中包含此类元素。

执行这些步骤后,您现在可以运行服务器,并且可以在生产模式下查看您的静态文件。

更新:如果您的版本 changelog 表示不再需要在您的 settings.py 文件中声明 WSGI_APPLICATION = 'projectName.wsgi.application'

【讨论】:

我做了相应的处理,在开发中效果很好,但在生产中却不行。当 DEBUG == False 时仍然有同样的问题 @AnnaHuang 你所说的开发和生产是什么意思?您有单独的环境或机器吗?它们的配置方式相同吗? @DarkCygnus 你的意思是“版本 > 4”吗? @AnnaHuang 您是否查看了这篇文章底部的更新?在我删除“WSGI_APPLICATION”设置后,它开始在生产中工作。【参考方案6】:

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

警告

这只有在 DEBUG 为 True 时才有效。

那是因为这种观点严重 效率低下,可能不安全。 这仅适用于本地 开发,永远不应该使用 正在生产中。

Docs: serving static files in developent

更新了link和this

编辑:您可以添加一些网址来测试您的 404 和 500 模板,只需在您的网址中使用通用视图 direct_to_template。

from django.views.generic.simple import direct_to_template

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

【讨论】:

如何在生产环境中提供静态文件? NVM,我刚看到。谢谢。 您将设置您的网络服务器来托管特定目录。最常见的是你会使用 Apache 或 Nginx。 The Docs 深入了解一下。 感谢@j_syk,我已经尝试过通过类似于您建议的其他非错误机制查看 404.html 和 500.html 的方法。但是我想知道是否完全不可能让我的页面像在生产中那样正确呈现,同时仍然只在我的测试服务器上运行——当调试关闭时,将静态文件处理委托给 Apache 为我解决了这个问题。感谢您的贡献。 @mcnemesis 我不确定会发生什么——但尝试设置 TEMPLATE_DEBUG=False 和 DEBUG=True。如果您关闭漂亮的错误,我不确定它是否会转到 404/500 模板 如预期的那样,这样做并没有产生任何积极的结果。但仍然感谢。【参考方案7】:

您实际上可以在生产 Django 应用程序中安全地提供静态文件,而无需 DEBUG=True

与其使用 Django 本身,不如在你的 WSGI 文件中使用dj_static (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())

【讨论】:

后来我发现了whitenoise,它可能功能更全。【参考方案8】:

您可以通过多种不同的方式对其进行调试。这是我的方法。

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

【讨论】:

【参考方案9】:

对于 Django 的最新版本,请在此处查看答案:https://***.com/a/7639983/6180987

对于 1.10 以下的 django 版本,该解决方案应该可以工作:

只需打开你的项目 urls.py,然后找到这个 if 语句。

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

您可以将 settings.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 ), ]

【讨论】:

您的代码是正确的,但是在 Django 1.10 中,配置是针对媒体的,静态是:urlpatterns += [ url(r'^media/(?P.*)$',服务, 'document_root': settings.MEDIA_ROOT, ), url(r'^static/(?P.*)$', serve, 'document_root': settings.STATIC_ROOT ), ]【参考方案10】:

这正是您必须在终端上键入才能在没有 DEBUG = TRUE 的情况下运行您的项目 然后您会看到所有资产(静态)文件都在本地服务器上正确加载。

python manage.py runserver --insecure 

--insecure : 表示你可以在没有安全模式的情况下运行服务器

【讨论】:

最简单的答案。添加中间件只是为了在开发中调试 404 样式是一种矫枉过正。有趣的是我去寻找这面旗帜,但在django's manage.py documentation page 上找不到任何提及【参考方案11】:

我同意 Marek Sapkota 的回答;但如果请求静态文件,您仍然可以使用 django URFConf 重新分配 url。

第一步:在settings.py中定义STATIC_ROOT路径

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

第 2 步:然后收集静态文件

$ python manage.py collectstatic

第 3 步:现在定义您的 URLConf,如果静态位于 url 的开头,则访问静态文件夹 staticfiles 中的文件。注意:这是您项目的 urls.py 文件:

from django.urls import re_path
from django.views.static import serve

urlpattern += [
  re_path(r'^static/(?:.*)$', serve, 'document_root': settings.STATIC_ROOT, )
]

【讨论】:

【参考方案12】:

最终解决方案:- 所以基本上当你使 debug = False 时,Django 不想处理你的静态文件。 所以我们想要一些可以处理我们文件的东西。 答案是白噪声。

    pip install whitenoise 在您的环境中

    在 settings.py 的中间件列表中添加 'whitenoise.middleware.WhiteNoiseMiddleware'

    这应该被添加到 'django.middleware.security.SecurityMiddleware' 的下方,以及所有剩余的中间件之上。这样您的中间件列表将如下所示:-

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'whitenoise.middleware.WhiteNoiseMiddleware',
        # add it exactlyhere
        'django.contrib.sessions.middleware.SessionMiddleware',
        '...'
    ]
    

    在已安装的应用之上添加 'whitenoise.runserver_nostatic' 这样您的已安装应用程序列表将如下所示:-

    INSTALLED_APPS = [
        'whitenoise.runserver_nostatic',
        'django.contrib.admin',
        'django.contrib.auth',
        '...'
    ]
    

完成,您现在可以在生产环境中提供静态文件了!!

【讨论】:

【参考方案13】:

这是正常的预期行为。

Warning

This will only work if DEBUG is True.  
you can actually view custom error views until Debug is Off  

如果 Django 只是从文件系统中读取并发送文件,那么它与普通的 Web 服务器相比没有优势,所有的 Web 服务器都能够自行处理文件。

此外,如果您使用 Django 提供静态文件,则 Python 进程将在请求期间保持忙碌,并且无法为更适合的动态请求提供服务。

由于这些原因,Django 静态视图仅设计用于开发期间,如果您的 DEBUG 设置为 False,则该视图将不起作用。

由于在开发过程中,我们通常一次只有一个人访问该网站( 开发人员),Django 可以提供静态文件。

【讨论】:

【参考方案14】:

当我制作 DEBUG = True 时,我的静态文件不起作用。

如果我在 python manage.py runserver --insecure 中运行我的项目。这样我也得到了我的静态。

解决方案 1:

python manage.py runserver --insecure

解决方案 2:

但我需要永久解决方案。然后我安装 pip install dj-static==0.0.6 并将一些代码添加到我的 wsgi.py 文件中:

from django.core.wsgi import get_wsgi_application
from dj_static import Cling

application = Cling(get_wsgi_application())

然后我在setting.py中添加了一些:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '/static/')
STATICFILES_DIRS = [
    BASE_DIR / "static",
]

【讨论】:

【参考方案15】:

不推荐使用对 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') ),
        )

【讨论】:

【参考方案16】:

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

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

并添加: url(r'^media/(?P&lt;path&gt;.*)$', serve, 'document_root': settings.MEDIA_ROOT, ), 在 urlpatterns 中。

【讨论】:

【参考方案17】:

nginx、设置和 url 配置

如果您使用的是 linux,这可能会有所帮助。

nginx 文件

your_machn:/#vim etc/nginx/sites-available/nginxfile

server 
    server_name xyz.com;

    location = /favicon.ico  access_log off; log_not_found off; 
    location /static/ 
        root /var/www/your_prj;
    

    location /media/ 
        root /var/www/your_prj;
    
...........
......

urls.py

​​>
.........
   .....
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('test/', test_viewset.TestServer_View.as_view()),
        path('api/private/', include(router_admin.urls)),
        path('api/public/', include(router_public.urls)),    
        ]
    
    if settings.DEBUG:
        import debug_toolbar
        urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
        urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

settings.py

​​>
.....
........
STATIC_URL = '/static/'
MEDIA_URL = '/media/'

STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
.....
....

确保运行:

(venv)yourPrj$ ./manage.py collectstatic
yourSys# systemctrl daemon-reload

【讨论】:

【参考方案18】:

虽然不是最安全的,但是可以在源代码中更改。导航到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 运行静态文件。

注意:信息只能用于测试

【讨论】:

以上是关于为啥 DEBUG=False 设置使我的 django 静态文件访问失败?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 unwind segue 会使我的应用程序崩溃?

使用 DEBUG 设置为 False 记录 Django SQL 查询

为啥意图使我的应用程序崩溃?

为啥我的班级用错误代码 138 使我的 OCUnit 测试用例崩溃?

Django 在 debug = False 时找不到我的媒体文件夹

为啥我的 ListView 使我的应用程序崩溃而不是列出我的条目?