如何调试使用 whitenoise、gunicorn 和 heroku 服务的 django 静态文件?

Posted

技术标签:

【中文标题】如何调试使用 whitenoise、gunicorn 和 heroku 服务的 django 静态文件?【英文标题】:How to debug django staticfiles served with whitenoise, gunicorn, and heroku? 【发布时间】:2020-07-22 17:50:50 【问题描述】:

我有一个通过 Dockerfile 和 heroku.yml 在 Heroku 上运行的项目。

该站点通常可以运行,但我在处理静态文件时遇到了问题。

collectstatic 在构建包时运行。

如果我将 DEBUG 设置为 True,它会找到文件。

我正在尝试使用白噪声,但不确定为什么它不起作用。这听起来很简单,所以我敢肯定这很愚蠢。

heroku.yml

setup:
    addons:
        - plan: heroku-postgresql
build:
    docker:
        web: Dockerfile
release:
    image: web
    command:
        - python manage.py collectstatic --noinput
run:
    web: gunicorn records_project.wsgi

settings.py

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    '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.contrib.sites.middleware.CurrentSiteMiddleware',
]
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'whitenoise.runserver_nostatic',
    'django.contrib.staticfiles',
    'django.contrib.sites',
    ... more stuff here...
# Static files (CSS, javascript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# for referencing files with a URL
STATIC_URL = '/static/'
# where to find static files when local
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]
# location of satatic files for production
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# how Django should look for static file directories; below is default
STATICFILES_FINDERS = [
    # defaults
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
# This gives me a 500 error
# STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

urls.py

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

【问题讨论】:

【参考方案1】:

我也遇到过这个问题。尽管在发布阶段成功收集静态文件,但在 dyno 启动时它们并不存在(因此 Django 缺少清单错误)。

此设置有效:

heroku.yml

build:
  docker:
    web: Dockerfile
run:
  web: ./heroku_entrypoint.sh

Dockerfile

--- some code ---

RUN chmod +x heroku_entrypoint.sh
RUN mkdir -p /app/static/

--- other code ---

heroku_entrypoint.sh

python manage.py collectstatic --noinput
python manage.py migrate
gunicorn app.wsgi:application --bind 0.0.0.0:$PORT

【讨论】:

【参考方案2】:

不管怎样,我从来没有找到让 WhiteNoise 为这些静态文件提供服务的方法。我发誓它在过去使用过类似的设置,所以这仍然是一个谜。

我收到了来自 justdjango.com 的 Matt 的提示,说 Heroku 不想从同一台服务器提供静态文件。将静态文件移至 AWS S3 存储桶后,一切正常。

【讨论】:

【参考方案3】:

我遇到了类似的问题,因为在发布阶段收集的静态文件在运行时丢失了。所以我将代码更改为:

heroku.yml

setup:
  addons:
    - plan: heroku-postgresql
build:
  docker:
    web: Dockerfile
release:
  image: web
  command:
    - chmod u+x entrypoint_heroku.sh
run:
  web: ./entrypoint_heroku.sh

Dockerfile

FROM python:3.7

WORKDIR /usr/src/app

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apt-get update
RUN apt install -y netcat

RUN pip install pipenv
COPY Pipfile* /usr/src/app/
RUN pipenv install --system --dev

COPY . /usr/src/app/

RUN mkdir -p /storage/static/

entrypoint_heroku.sh

#!/bin/sh
python manage.py migrate --noinput
python manage.py collectstatic --noinput
gunicorn app.wsgi

settings.py

STATIC_URL = '/static/'
MEDIA_ROOT = '/storage/'
STATIC_ROOT = MEDIA_ROOT + 'static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

不是最好的解决方案。但它帮助我使用 Debug=False 运行服务器

【讨论】:

感谢您的提示。有机会我会试试这个。 很奇怪。即使使用 chmod 命令,当它尝试运行 entrypoint_heroku.sh 时,我也会收到权限被拒绝错误。【参考方案4】:

您是否有可能在模板中引用了不存在的静态文件(例如 CSS 文件或图像)?我遇到了同样的问题,因为我的基本模板中有以下内容:

<link rel="stylesheet" href="% static 'css/styles.css' %"> 

但我的 css 文件夹中没有 styles.css 文件。

【讨论】:

感谢您的回复。我不认为是这样,但也许我错了。这是我所知道的一个例子:这些都在我的&lt;head&gt;...&lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css"&gt; &lt;link rel="stylesheet" href="/static/css/base.css"&gt; 第一个加载良好。第二个在控制台中给我错误:Refused to apply style from 'https://subdomain.domain.com/static/css/base.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled. 抱歉,直接回答您:我有这些文件,但无法在管理员中加载样式表。 /static/css/base.css 可能是问题所在。尝试在您的模板中使用% static 'css/base.css' %。您还需要在模板顶部包含% load static % 抱歉造成混淆:我已经在模板顶部使用% load static % 并使用% static 'css/base.css' % 呈现指向该CSS 文件的链接。 /static/css/base.css 是模板在浏览器中呈现的内容。 我看到您已将STATICFILES_STORAGE 注释掉。我想你需要那个。我也收到了 500 错误。丢失或错误引用的静态文件将导致 500 错误。如果不是这样,我不知道会是什么。祝你好运!

以上是关于如何调试使用 whitenoise、gunicorn 和 heroku 服务的 django 静态文件?的主要内容,如果未能解决你的问题,请参考以下文章

Django:Whitenoise 在调试错误的情况下无法在生产中工作

django/whitenoise 存储后端导致错误

仅使用 gunicorn、django 和 whitenoise 我如何提供媒体服务?

Whitenoise 应该自动压缩静态文件吗?如何?

如何在 Django 中为 WhiteNoise 5.1.0 设置 wsgi.py 文件?

flask&nginx&gunicore??????