ValueError:在带有 Docker、django-pipeline、whitenoise 的 Heroku 上缺少静态文件清单条目

如何解决ValueError:在带有 Docker、django-pipeline、whitenoise 的 Heroku 上缺少静态文件清单条目

我正在尝试使用 Docker、django-pipeline 和 whitenoise 在 Heroku 上部署 Django 项目。容器构建成功,我看到 collectstaticcontainer-name/static生成了预期的文件。但是,在访问任何页面时,我都会收到以下 500 错误

ValueError: Missing staticfiles manifest entry for 'pages/images/favicons/apple-touch-icon-57x57.png'

下面是我的 settings.pyDockerfileheroku.yml。由于我也在使用 django-pipeline,我不确定的一件事是 STATICFILES_STORAGE 使用什么设置?我试过了

STATICFILES_STORAGE = 'pipeline.storage.Pipelinestorage'

但这会导致文件路径 404ing。

任何建议表示赞赏。谢谢。

#settings.py
...
# Security WARNING: don't run with debug turned on in production!
DEBUG = env.bool("DJANGO_DEBUG",default=False)

ALLOWED_HOSTS = ['.herokuapp.com','localhost','127.0.0.1']

INSTALLED_APPS = [
    "django.contrib.admin","django.contrib.admindocs","django.contrib.auth","django.contrib.contenttypes","django.contrib.sessions","django.contrib.messages","django.contrib.staticfiles","django.contrib.sites",# Third-party
    "allauth","allauth.account","debug_toolbar","django_extensions","pipeline","rest_framework","whitenoise.runserver_nostatic","widget_tweaks",# Local
    ...
]
MIDDLEWARE = [
    "debug_toolbar.middleware.DebugToolbarMiddleware","django.middleware.security.SecurityMiddleware","whitenoise.middleware.WhiteNoiseMiddleware",...
]

# Static files (CSS,JavaScript,Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = "/static/"
# STATICFILES_Dirs = [str(BASE_DIR.joinpath("code/static"))]
STATIC_ROOT = str(BASE_DIR.joinpath("static"))

MEDIA_URL = "/media/"

MEDIA_ROOT = str(BASE_DIR.joinpath("media"))

# django-pipeline config
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesstorage"
DEBUG_PROPAGATE_EXCEPTIONS = True
STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder","django.contrib.staticfiles.finders.AppDirectoriesFinder","pipeline.finders.PipelineFinder",)
...
# Dockerfile
# Pull base image
FROM python:3.8

# Set environment variables and build arguments
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs build-essential

# Set working directory
workdir /code
copY . /code/
RUN npm install sass --dev
RUN npm install yuglify --dev
RUN npm install
RUN mkdir static
RUN mkdir staticfiles

# Install dependencies
copY Pipfile Pipfile.lock /code/
# figure out conditional installation of dev dependencies
# Will need to remove --dev flag for production
RUN pip install pipenv && pipenv install --system --dev
# heroku.yml
setup:
  addons:
  - plan: heroku-postgresql
build:
  docker:
    web: Dockerfile
release:
  image: web
  command:
    - python manage.py collectstatic --noinput
run:
  web: gunicorn config.wsgi

更新

根据 ENDEESA 对 this similar SO post 的回应,我将我的设置更新为以下内容,因为我的静态文件存储在 pages/static/pages 中:

STATIC_URL = "/static/"
STATICFILES_Dirs = [str(BASE_DIR.joinpath("pages/static"))]
STATIC_ROOT = str(BASE_DIR.joinpath("static"))

我还注意到我的顶级 urls.py 文件包含以下行:

urlpatterns += staticfiles_urlpatterns()

据我所知,这对于在开发中提供静态文件很有用,但不应在生产中使用,因此我将其移至仅在 DEBUG 为 True 时添加。但遗憾的是,错误仍然存​​在。

更神秘的是,当我跑步时

python manage.py findstatic <file-path> --verbosity 2

找到文件

Found 'images/favicons/apple-touch-icon-57x57.png' here:
  /code/pages/static/images/favicons/apple-touch-icon-57x57.png
  /code/pages/static/images/favicons/apple-touch-icon-57x57.png
Looking in the following locations:
  /code/pages/static
  /code/static
  /usr/local/lib/python3.8/site-packages/django/contrib/admin/static
  /usr/local/lib/python3.8/site-packages/debug_toolbar/static
  /usr/local/lib/python3.8/site-packages/django_extensions/static
  /usr/local/lib/python3.8/site-packages/rest_framework/static

那为什么我仍然收到 ValueError: Missing staticfiles manifest entry

解决方法

已解决

终于,我得出了以下解决方案。我的主要问题是:

  • 静态文件似乎是在发布命令期间收集的,但实际的 STATIC_ROOT 目录在我的容器中是空的。我不知道为什么。我的解决方案是不在 collectstatic 中将 heroku.yml 作为发布命令运行,而是在 Dockerfile 中这样做。
  • 注意:为了在我的 collectstatic 中设置 Dockerfile,我需要为所有环境变量设置默认值,包括 SECRET_KEY,后者我使用 get_random_secret_key()来自django.core.management.utils。感谢Ryan Knightillustrating this here提供服务。
  • 除了我的 settings.py 需要默认密钥外,我的最终静态文件设置如下所示。
  • 由于我使用了 django-pipeline,因此我的 js 文件无法通过 whitenoise 存储选项正确加载。我最终使用了 pipeline.storage.PipelineStorage
  • 结果证明我根本不需要设置 STATICFILES_DIRS。以前我将其设置为:
STATICFILES_DIRS = [
    str(BASE_DIR.joinpath("pages/static")),str(BASE_DIR.joinpath("staticfiles")),]

两者都是不必要的,因为 app_name/static/app_name 已经是 default place Django will look for static files,而且我实际上并没有在 root/staticfiles 中存储额外的非应用特定文件。所以我删除了这个设置。

  • heroku.yml 中,我删除了 collectstatic 的释放命令。
  • 在 Heroku 应用管理员的“设置”页面上,我为 DISABLE_COLLECTSTATIC 添加了一个配置变量,设置为 1
# Dockerfile
# Pull base image
FROM python:3.8

# Set environment variables and build arguments
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs build-essential

# Set working directory
WORKDIR /code
COPY . /code/
RUN npm install sass --dev
RUN npm install yuglify --dev
RUN npm install

# Install dependencies
COPY Pipfile Pipfile.lock /code/
RUN pip install pipenv && pipenv install --system

# Collect static files here instead of in heroku.yml so they end up in /code/static,as expected in the app
RUN python manage.py collectstatic --noinput
# settings.py
...
from django.core.management.utils import get_random_secret_key
SECRET_KEY = env("DJANGO_SECRET_KEY",default=get_random_secret_key())
...
STATIC_URL = "/static/"
STATIC_ROOT = str(BASE_DIR.joinpath("static"))
STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
DEBUG_PROPAGATE_EXCEPTIONS = True
STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder","django.contrib.staticfiles.finders.AppDirectoriesFinder","pipeline.finders.PipelineFinder",)
...
# heroku.yml
setup:
  addons:
  - plan: heroku-postgresql
build:
  docker:
    web: Dockerfile
release:
  image: web
run:
  web: gunicorn config.wsgi

项目结构,以防万一:

config
  settings.py
  ...
pages
  static
    pages
      scss
      js
      images
static
Dockerfile
heroku.yml
docker-compose.yml
...

祝所有与部署之神战斗的人好运。愿机会永远对你有利,不要放弃!

,

@内森

在此处收集静态文件而不是在 heroku.yml 中,以便它们最终出现在 /code/static 中,正如应用中的预期

RUN python manage.py collectstatic --noinput

这为我节省了 3 天的忙碌时间。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?