在 Heroku 上找不到 Django 静态文件(带白噪声)

Posted

技术标签:

【中文标题】在 Heroku 上找不到 Django 静态文件(带白噪声)【英文标题】:Django staticfiles not found on Heroku (with whitenoise) 【发布时间】:2016-06-01 03:13:42 【问题描述】:

这个问题似乎被问了好几次,但我无法解决。

我使用DEBUG = False 在生产环境中部署了一个 django 应用程序。我设置了我的allowed_host。 我使用% load static from staticfiles % 加载静态文件。我完全编写了 Heroku doc 所建议的设置:

BASE_DIR = os.path.dirname(os.path.dirname(__file__))
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(PROJECT_ROOT, 'static'),
)

STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

但我收到了错误 500。并得到了这个回溯(通过邮件)

...
`cache_name = self.clean_name(self.hashed_name(name))
 File "/app/.heroku/python/lib/python3.5/site-    packages/django/contrib/staticfiles/storage.py", line 94, in hashed_name (clean_name, self))
...
ValueError: The file ‘app/css/font.css’ could not be found with <whitenoise.django.GzipManifestStaticFilesStorage object at 0x7febf600a7f0>.`

当我运行heroku run python manage.py collectstatic --noinput 一切似乎都很好:

276 static files copied to '/app/annuaire/staticfiles', 276 post-processed.

有没有人可以帮帮我?

谢谢

编辑:

annuaire
|-- /annuaire
|-- -- /settings.py
|-- /app
|-- -- /static/...`

wsgi.py

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


application = get_wsgi_application()
application = DjangoWhiteNoise(application)

【问题讨论】:

Django 通常只在 DEBUG=False 时调用该特定函数,所以我很困惑你会在 DEBUG=True 时得到该错误。我建议使用 DEBUG=False 在本地测试您的应用程序,运行collectstatic,然后运行runserver,看看您是否收到该错误。会不会是你还没有提交那个特定的文件? 对不起!当 Debug 为 False 时,你是对的! 您是否打印了STATIC_ROOT 以确保它与'/app/annuaire/staticfiles' 相同? 我刚做了(本地)我得到了In [3]: settings.STATIC_ROOT Out[3]: '/Users/vincentpoulain/xxxx/annuaire/annuaire/staticfiles':/ 我尝试改成STATIC_ROOT = os.path.join(BASE_DIR, '../app/staticfiles') 【参考方案1】:

对于 BASE_DIR,如果您的设置不在根目录中而是在 /projectname/ 文件夹中,则需要双目录名:

settings.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
# for /static/root/favicon.ico    
WHITENOISE_ROOT = os.path.join(BASE_DIR, 'staticfiles', 'root') 

模板.html

%  load staticfiles %
<link rel="stylesheet" href="%  static "app/css/font.css" %">

此示例的应用树:

annuaire
|-- /annuaire
|-- -- /settings.py
|-- /app
|-- /static/app/css/font.css

【讨论】:

谢谢!我做到了,但它仍然不起作用......我在主要问题帖子中编辑了我的 django 应用程序树。 当我收到 275 static files copied to '/app/staticfiles', 1 unmodified, 276 post-processed. 时,这很奇怪,但在 heroku bash 上:staticfiles 仍然是空的 ... @vpoulain 这是因为每个新的 Heroku 进程都在其自己的临时文件系统中运行,因此任何其他进程都不会看到新文件。 (见devcenter.heroku.com/articles/dynos#ephemeral-filesystem)。 collectstatic 必须在初始推送期间运行才能持久保存文件。 @vpoulain 检查应用程序树,对于您的代码,我认为您需要使用 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'app','static'), ) 或将静态文件夹移动到根 @Meska 这有点混乱,在哪里写staticfiles,在哪里写static【参考方案2】:

我明白了。我需要添加

python manage.py collectstatic --noinput;

在我的 Procfile 中。 Heroku doc 说collecticstatic 是自动触发的。 https://devcenter.heroku.com/articles/django-assets

谢谢

【讨论】:

或者只是通过dashboard从您的应用设置中删除环境变量DISABLE_COLLECTSTATIC。重要的是:不要将其值变为 0,只需完全删除此环境变量即可。这样您就不必编辑您的Procfile。然后,一切都应该工作(至少他们为我工作!)。致谢:YunoJuno.【参考方案3】:

有了DEBUG=False,原来用来工作的东西不再适合我了。

但是,通过在settings.py 中的MIDDLEWARE 上启用whitenoise 解决了这个问题。最好在SecurityMiddleware下方。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', # add this line
    #Other middleware...
]

```

根据docs,其实首先需要开启。

【讨论】:

这对我有用。在 heroku 的启动 django 说明中,他们说要包含它 devcenter.heroku.com/articles/django-assets,但我从他们的 heroku-django-template github.com/heroku/heroku-django-template 开始,它没有包含在其中【参考方案4】:

问题在于 Heroku 中的 Python 应用程序使用内置的 Web 服务器,并且不提供静态文件。

您可以使用whitenoise的应用程序,这个工作解决方案是100%。

假设你已经生成了静态文件,例如:

$ python manage.py collectstatic

接下来你需要这样做:

1) $ pip install whitenoise

2) 在您的 requirements.txt

中添加字符串“whitenoise==3.3.0”

3) 在settings.py

中添加代码
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

4) 在 app/wsgi.py

中添加此代码
from whitenoise.django import DjangoWhiteNoise
application = DjangoWhiteNoise(application)

【讨论】:

不再需要修改wsgi.py【参考方案5】:

除了上面的答案,也可能是你没有指定正确的STATIC_ROOT,如https://docs.djangoproject.com/en/2.0/howto/static-files/#deployment

所述

对我来说,解决方案是将其添加到我的生产 settings.py 的末尾

STATIC_ROOT = "/app/static/"

要知道你的静态文件夹在你的heroku中的位置,运行这个

heroku run python manage.py collectstatic

然后你会看到那里显示的路径。

【讨论】:

【参考方案6】:

对我来说,以下工作。

settings.py

DEBUG = True

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') #this is not used
# Add static folder to STATIC_DIRS
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

urls.py

from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [

] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

注意

此帮助函数仅在调试模式下有效,并且仅当给定 前缀是本地的(例如 /static/)而不是 URL(例如 http://static.example.com/)。

此外,此辅助函数仅服务于实际的 STATIC_ROOT 文件夹; 它不会像这样执行静态文件发现 django.contrib.staticfiles.

【讨论】:

【参考方案7】:

我苦苦挣扎了几个小时,直到我终于找到了问题所在。我认为的主要问题是,在Heroku official documentation 中,他们使用了旧式中间件,该中间件使用了已弃用的MIDDLEWARE_CLASSES,而不是新的MIDDLEWARE 设置。

在 whitenoise 版本 4+ 中,已删除 Django 的 WSGI 集成选项(涉及编辑 wsgi.py)。相反,您应该将 WhiteNoise 添加到 settings.py 中的中间件列表中,并从 wsgi.py 中删除对 WhiteNoise 的任何引用。 (来自the docs)

以下配置就像一个魅力:

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

MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    # the next line of code is the one that solved my problems
    'whitenoise.middleware.WhiteNoiseMiddleware',

]

注意以下注释,同样来自文档。

您可能会发现其他第三方中间件建议将其置于中间件列表顶部的最高优先级。除非您确切了解正在发生的事情,否则您应该忽略此建议并始终将 WhiteNoiseMiddleware 置于其他中间件之上

【讨论】:

【参考方案8】:

我也遇到了同样的问题。找到问题的最简单方法是使用

heroku run ls staticfiles/images

如果图像位于您的文件所在的目录中。这将为您提供该目录中所有文件的列表。

我发现这是文件扩展名中的一个案例问题。该文件有一个扩展名.JPG,我在模板上用扩展名.jpg引用了它

【讨论】:

【参考方案9】:

$ pip install whitenoise

在中间件中添加白噪声。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
]

还需要在setting.py中添加STATIC_ROOT

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

并在 urls.py 中添加 media_root

from django.conf import settings

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \
        + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

然后您可以在本地或服务器上运行 collectstatic 命令 python manage.py collectstatic

它会正常工作。您可以在本地运行此命令 collectstatic ,它将在服务器上运行。

【讨论】:

以上是关于在 Heroku 上找不到 Django 静态文件(带白噪声)的主要内容,如果未能解决你的问题,请参考以下文章

在heroku上找不到gunicorn

Django 在服务器上找不到静态文件,但在本地机器上工作正常

错误:在 Heroku 上找不到模块 Discord.js

在 Heroku 上找不到类“Memcached”

rails 应用程序在 heroku 上找不到 fontawesome 图标

在 Heroku 上找不到资源“语料库/wordnet”