【问题标题】:ValueError: Missing staticfiles manifest entry for 'favicon.ico'ValueError:缺少“favicon.ico”的静态文件清单条目
【发布时间】:2017-10-24 22:23:24
【问题描述】:

我在运行python manage.py test 时得到ValueError。我的项目名为fellow_go,我目前正在开发一个名为pickup 的应用程序。

请注意,这个错误是在最近对 Django 的提交中添加的:Fixed #24452 -- Fixed HashedFilesMixin correctness with nested paths.

======================================================================
ERROR: test_view_url_exists_at_desired_location (pickup.tests.test_view.HomePageViewTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/sunqingyao/PycharmProjects/fellow_go/pickup/tests/test_view.py", line 10, in test_view_url_exists_at_desired_location
    resp = self.client.get('/', follow=True)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/test/client.py", line 536, in get
    **extra)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/test/client.py", line 340, in get
    return self.generic('GET', path, secure=secure, **r)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/test/client.py", line 416, in generic
    return self.request(**r)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/test/client.py", line 501, in request
    six.reraise(*exc_info)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/utils/six.py", line 686, in reraise
    raise value
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/core/handlers/base.py", line 217, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/core/handlers/base.py", line 215, in _get_response
    response = response.render()
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/response.py", line 107, in render
    self.content = self.rendered_content
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/response.py", line 84, in rendered_content
    content = template.render(context, self._request)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/backends/django.py", line 66, in render
    return self.template.render(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/base.py", line 207, in render
    return self._render(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/test/utils.py", line 107, in instrumented_test_render
    return self.nodelist.render(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/loader_tags.py", line 177, in render
    return compiled_parent._render(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/test/utils.py", line 107, in instrumented_test_render
    return self.nodelist.render(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/templatetags/static.py", line 105, in render
    url = self.url(context)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/templatetags/static.py", line 102, in url
    return self.handle_simple(path)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/templatetags/static.py", line 117, in handle_simple
    return staticfiles_storage.url(path)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/contrib/staticfiles/storage.py", line 162, in url
    return self._url(self.stored_name, name, force)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/contrib/staticfiles/storage.py", line 141, in _url
    hashed_name = hashed_name_func(*args)
  File "/Users/sunqingyao/Envs/django_tutorial/lib/python3.6/site-packages/django/contrib/staticfiles/storage.py", line 432, in stored_name
    raise ValueError("Missing staticfiles manifest entry for '%s'" % clean_name)
ValueError: Missing staticfiles manifest entry for 'favicon.ico'

----------------------------------------------------------------------

fellow_go/settings.py

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

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]

# ......

# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

fellow_go/urls.py

urlpatterns = i18n_patterns(
    url(r'^$', HomePageView.as_view(), name='index'),
    url(r'^pickup/', include('pickup.urls')),
    url(r'^accounts/', include('django.contrib.auth.urls')),
    url(r'^admin/', admin.site.urls),
    prefix_default_language=False
) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

fellow_go/pickup/views.py

class HomePageView(TemplateView):

    template_name = 'index.html'

fellow_go/templates/index.html

<link rel="icon" href="{% static "favicon.ico" %}">

fellow_go/pickup/tests/test_view.py

class HomePageViewTest(TestCase):

    def test_view_url_exists_at_desired_location(self):
        resp = self.client.get('/', follow=True)
        self.assertEqual(resp.status_code, 200)

我有一个favicon.ico 文件:


奇怪的是,python manage.py runserver 没有发生错误:

/Users/sunqingyao/Envs/django_tutorial/bin/python3.6 /Users/sunqingyao/PycharmProjects/fellow_go/manage.py runserver 8000
Performing system checks...

System check identified no issues (0 silenced).
May 24, 2017 - 22:09:25
Django version 1.11.1, using settings 'fellow_go.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[24/May/2017 22:09:28] "GET / HTTP/1.1" 200 6276
[24/May/2017 22:09:28] "GET /static/css/style.min.css HTTP/1.1" 200 2474
[24/May/2017 22:09:28] "GET /static/css/ie10-viewport-bug-workaround.css HTTP/1.1" 200 430
[24/May/2017 22:09:28] "GET /static/js/ie10-viewport-bug-workaround.js HTTP/1.1" 200 685
[24/May/2017 22:09:28] "GET /static/js/opt-in.js HTTP/1.1" 200 511
[24/May/2017 22:09:28] "GET /static/css/datetimepicker.css HTTP/1.1" 200 12351
[24/May/2017 22:09:28] "GET /static/js/bootstrap-datetimepicker.js HTTP/1.1" 200 55741
[24/May/2017 22:09:35] "GET /static/favicon.ico HTTP/1.1" 200 766
Not Found: /apple-touch-icon-precomposed.png
[24/May/2017 22:09:35] "GET /apple-touch-icon-precomposed.png HTTP/1.1" 404 2678
Not Found: /apple-touch-icon.png
[24/May/2017 22:09:35] "GET /apple-touch-icon.png HTTP/1.1" 404 2642

请告诉我我的代码有什么问题。

【问题讨论】:

    标签: python django static django-views django-staticfiles


    【解决方案1】:

    我有同样的问题;每次使用 DEBUG = False 运行服务器时,我都会收到“缺少静态文件清单条目”。

    我花了好几个小时才发现问题出在我的静态链接开头包含“/”。

    例如: {% static '/app/styles/main.css' %} 而不是 {% static 'app/styles/main.css' %}

    【讨论】:

      【解决方案2】:

      环境:Python 3.8、Django 3.1.5

      基本上我不使用白噪声。在我看来,Django 的ManifestStaticFilesStorage 类在收集静态文件方面做得很好。它添加了唯一的哈希,运行速度很快,不需要任何其他依赖项。

      在生产服务器上(静态文件由 nginx 从“公共”文件夹提供)我的静态文件设置如下所示:

      STATIC_URL = '/static/'
      STATIC_ROOT = os.path.join(BASE_DIR, 'public', 'static')
      STATICFILES_DIRS = [
          os.path.join(BASE_DIR, 'static')
      ]
      
      STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
      

      仅此而已。在运行python manage.py collectstatic 后使用此配置,Django 将从static 文件夹中获取所有文件并将其移动到public。它还将创建具有唯一 ID 的每个文件的副本,并将创建 staticfiles.json,其中包含所有带有原始静态文件名称及其“散列”版本的静态文件映射,例如

      {... "css/main.css": "css/main.31cdb680414e.css", main.js": "main.b08f762abac7.js"...}
      

      如果您在模板中使用这种方法:{% static 'images/my-image.jpg' %},它将被转换为path_to_image/my-image.828172380.jpg 特别是如果您更改 css 或 js 文件中的某些内容并希望将更改应用于所有内容而无需清除浏览器缓存,这非常方便。

      重要提示 如果您将在开头添加带有斜线的静态文件,您可能会遇到此处描述的问题“Missing staticfiles manifest for...”。所以在你的模板中:

      这会起作用

      <div class="slide slide1" style="background-image: url('{% static 'images/slider/129557309.jpg' %}');">
      

      这是错误的,不起作用,你会有异常

      <div class="slide slide1" style="background-image: url('{% static '/images/slider/129557309.jpg' %}');">
      

      差别很小,但你必须记住它。希望它会有所帮助:)

      【讨论】:

        【解决方案3】:

        在我的情况下,这是因为我使用 nginx (Docker) 来提供静态图像。这发生在应用程序运行时,而不是像 OP 这样的测试期间。

        问题是我将 STATIC_ROOT 声明在 Django 应用程序之外:

        STATIC_ROOT = "../staticfiles"
        

        我这样做是为了避免将资产不必要地复制到 Django 容器中。如果您使用默认的STATICFILES_STORAGE,这可以正常工作,但是当使用ManifestStaticFilesStorage 时,静态文件查找会失败,因为它在 Django 容器的目录中找不到清单文件资产。

        解决方案是简单地声明静态文件出现在 Django 图像上:

        STATIC_ROOT = "staticfiles"
        

        这确实会创建静态文件的副本:一份在 nginx 容器上,一份在 Django 上,但这意味着 Django 查找逻辑成功,即使文件是从 nginx 提供的。

        另一种选择是禁用manifest_strict 属性:

        storage.ManifestStaticFilesStorage.manifest_strict

        如果在运行时在 staticfiles.json 清单中找不到文件,则 引发了 ValueError。可以通过子类化来禁用此行为 ManifestStaticFilesStorage 并将 manifest_strict 属性设置为 False - 不存在的路径将保持不变。

        【讨论】:

          【解决方案4】:

          在最新版本的 Whitenoise(当前为 5.2)中,您现在可以这样做......

          WHITENOISE_MANIFEST_STRICT = False
          

          【讨论】:

          • 在 Whitenoise 文档中也看到了这一点,但对我不起作用。要对此进行测试,请在使用 whitenoise.storage.CompressedManifestStaticFilesStorage 时有意引用丢失的文件。对我来说,运行 Django==3.1.2 和你提到的相同版本的 Whitenoise,错误仍然存​​在。
          • 这解决了我的问题,谢谢!
          【解决方案5】:

          This answer 帮我解决了这个问题。

          首先在settings.py中添加这个

          LOGGING = {
          'version': 1,
          'disable_existing_loggers': False,
          'formatters': {
              'verbose': {
                  'format': ('%(asctime)s [%(process)d] [%(levelname)s] '
                             'pathname=%(pathname)s lineno=%(lineno)s '
                             'funcname=%(funcName)s %(message)s'),
                  'datefmt': '%Y-%m-%d %H:%M:%S'
              },
              'simple': {
                  'format': '%(levelname)s %(message)s'
              }
          },
          'handlers': {
              'null': {
                  'level': 'DEBUG',
                  'class': 'logging.NullHandler',
              },
              'console': {
                  'level': 'INFO',
                  'class': 'logging.StreamHandler',
                  'formatter': 'verbose'
              }
          },
          'loggers': {
              'django': {
                  'handlers': ['console'],
                  'level': 'DEBUG',
                  'propagate': True,
              },
              'django.request': {
                  'handlers': ['console'],
                  'level': 'DEBUG',
                  'propagate': False,
              },
          }}
          

          如果你使用 django-heroku,然后在你的 settings.py 末尾添加这个:

          django_heroku.settings(config=locals(), staticfiles=False,logging=False)
          

          【讨论】:

            【解决方案6】:

            尝试运行:

            python manage.py collectstatic
            

            测试现在有效吗?如果是这样,这可能是导致问题的配置:

            STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
            

            从 whitenoise v4 开始,这将失败,您应该使用:

            STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
            

            相关:
            https://stackoverflow.com/a/32347324/2596187

            查看 Django 文档: https://docs.djangoproject.com/en/1.11/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_strict

            【讨论】:

            • 我发现这很有用。 stackoverflow.com/questions/50009055/…
            • 运行“python manage.py colecstatic”(再次)并刷新网站,应该可以了。
            • 只是为了补充@emazzotta 的回答。我必须运行heroku run python3 manage.py collectstatic,它对我有用。
            • 此选项已在 whitenoise v4 whitenoise.evans.io/en/stable/changelog.html#v4-0 中删除,请告知如何使用 v4 解决此问题
            • OP 小心地指出他们“确实有一个favicon.ico 文件”,但这里提醒您在重新运行之前仔细检查该文件是否应该在它的位置@ 987654330@ 我在部署过程中不知何故搞砸了文件传输过程,以至于 favicon 文件被留下了,而所有其他图像都在它们应该在的地方。该站点在DEBUG 设置为True 时运行良好,但由于禁用调试而中断,OP 遇到了同样的错误。重新运行 collectstatic 并没有帮助,直到将 favicon 放入静态目录中,如设置中指定的那样。
            【解决方案7】:

            我的setting.py中有这个

            DEBUG = False
            try:
                from .local_setting import *
            except ImportError:
                pass
            

            删除 try 块后,一切都恢复正常了。

            【讨论】:

            • 只有DEBUG=False,和这个问题有关,如果你设置成DEBUG=True也一样。
            【解决方案8】:

            就我而言,我不确定它为什么会发生,但是在我删除 heroku 设置 django_heroku.settings(locals()) 之后,一切都恢复了。

            【讨论】:

              【解决方案9】:

              我遇到了同样的问题,我通过将STATICFILES_STORAGE 更改为:

              STATICFILES_STORAGE = 'cloudinary_storage.storage.StaticHashedCloudinaryStorage'
              

              那么你应该运行:

              python manage.py collectstatic
              

              【讨论】:

                【解决方案10】:

                只是分享我对这个问题的解决方案,以防它帮助其他人。

                我不小心在一些静态 URL 中包含了前导“/”,导致它们从清单中丢失。

                解决方案是替换以下所有实例:

                {% static '/path/to/some/file' %}

                {% static 'path/to/some/file' %}

                然后一切正常。

                【讨论】:

                • 不敢相信后端会因此而崩溃。经过无数天的白噪声配置。你先生刚刚赢得了互联网。
                • 太烦人了,Django 不能正确处理它!
                • 很好,一百万年后就不会这样了哈哈 - 不是为了未来的读者只有在设置白噪声后才有这个问题......当我在 nginx 中处理静态文件时,这没关系
                • 谢谢!我正在拔头发:)
                • 这也是我的问题。我不得不使用我的 IDE 的“全局站点”搜索“{% static '/”来找到错误的静态链接!
                【解决方案11】:

                如果您在测试期间引用静态文件,但您在创建该文件 (see these docs) 后尚未运行 ./manage.py collectstatic,Django 会引发此异常。

                解决此问题的推荐方法是:

                在测试期间,确保将 STATICFILES_STORAGE 设置设置为其他值,例如“django.contrib.staticfiles.storage.StaticFilesStorage”(默认值)。

                这是在您的settings.py 中执行此操作的简单方法:

                import sys
                
                TESTING = len(sys.argv) > 1 and sys.argv[1] == 'test'
                
                STATICFILES_STORAGE = (
                    'django.contrib.staticfiles.storage.StaticFilesStorage'
                    if TESTING
                    else 'whitenoise.storage.CompressedManifestStaticFilesStorage'
                )
                

                【讨论】:

                • 这对我有用
                【解决方案12】:

                whitenoise 包不一定会发生这种情况。将STATIC_STORAGE 更改为django.contrib.staticfiles.storage.ManifestStaticFilesStorage 将在运行以Django 1.11 开头的测试时产生相同的错误。

                发生这种情况是因为ManifestStaticFilesStorage 期望staticfiles.json 存在并且contain 要求的文件。您可以通过运行 ./manage.py collectstatic 并重试来确认这一点。

                您在开发中通常不会看到此错误,因为当 DEBUG == TrueManifestStaticFilesStorage 切换到 non-hashed 网址时。

                要克服这个问题,您必须确保:

                STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
                

                这是默认设置。

                一种方法是覆盖测试类的设置:

                from django.test import TestCase, override_settings
                @override_settings(STATICFILES_STORAGE='django.contrib.staticfiles.storage.StaticFilesStorage')
                class MyTest(TestCase):
                    pass
                

                或方法:

                from django.test import TestCase, override_settings
                class MyTest(TestCase):
                    @override_settings(STATICFILES_STORAGE='django.contrib.staticfiles.storage.StaticFilesStorage')
                    def test_something(self):
                        pass
                

                【讨论】:

                  【解决方案13】:

                  如果您想在 Django 1.11(或更新版本)项目中继续使用WhiteNoise 模块,同时防止出现“Missing staticfiles manifest entry”错误,您需要通过继承禁用manifest_strict 属性,如在Django documentation 中注明。

                  如何做到这一点?

                  首先,在你的项目目录中创建一个storage.py 文件:

                  from whitenoise.storage import CompressedManifestStaticFilesStorage
                  
                  
                  class WhiteNoiseStaticFilesStorage(CompressedManifestStaticFilesStorage):
                      manifest_strict = False
                  

                  其次,编辑settings.py 文件中的STATICFILES_STORAGE 常量,使其指向这个新类,例如:

                  STATICFILES_STORAGE = 'my_project.storage.WhiteNoiseStaticFilesStorage'
                  

                  【讨论】:

                  猜你喜欢
                  • 2020-11-19
                  • 2018-10-05
                  • 2020-02-01
                  • 2020-01-15
                  • 2023-03-06
                  • 2020-11-18
                  • 1970-01-01
                  • 2021-06-06
                  • 2017-12-29
                  相关资源
                  最近更新 更多