ValueError:缺少静态文件清单' favicon.ico'

时间:2017-05-24 14:01:01

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

我在运行ValueError时获得python manage.py test。我的项目名为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 /拾取/ views.py

class HomePageView(TemplateView):

    template_name = 'index.html'
  

fellow_go /模板/ index.html中

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

fellow_go /拾取/测试/ 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个文件:

enter image description here

奇怪的是,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

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

13 个答案:

答案 0 :(得分:41)

尝试跑步:

python manage.py collectstatic

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

STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

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

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

答案 1 :(得分:12)

如果您想继续在Django 1.11(或更高版本)项目中使用WhiteNoise模块,同时防止出现“缺少静态文件清单输入”错误,则需要通过以下方式禁用manifest_strict属性如Django documentation所述。

如何实现?

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

from whitenoise.storage import CompressedManifestStaticFilesStorage


class WhiteNoiseStaticFilesStorage(CompressedManifestStaticFilesStorage):
    manifest_strict = False

第二,在STATICFILES_STORAGE文件中编辑settings.py常量以指向该新类,例如:

STATICFILES_STORAGE = 'my_project.storage.WhiteNoiseStaticFilesStorage'

答案 2 :(得分:6)

只需分享我对此问题的解决方案,以防它对其他人有帮助。

我不小心在某些静态URL中加入了前导“ /”,从而导致清单中缺少它们。

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

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

使用

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

然后一切正常。

答案 3 :(得分:2)

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

之所以会这样,是因为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

答案 4 :(得分:2)

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

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

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

答案 5 :(得分:1)

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

推荐的解决方法是:

  

在测试期间,请确保将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'
)

答案 6 :(得分:1)

我的环境中有这个。py

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

我删除了try块之后,一切又恢复正常了。

答案 7 :(得分:0)

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

STATICFILES_STORAGE = 'cloudinary_storage.storage.StaticHashedCloudinaryStorage'

然后您应该运行:

python manage.py collectstatic

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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)

答案 10 :(得分:0)

在最新版本的Whitenoise(当前为5.2)中,您可以执行此操作。

WHITENOISE_MANIFEST_STRICT = False

答案 11 :(得分:0)

在我的情况下,这是因为我正在使用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 –不存在的路径将保持不变。

答案 12 :(得分:0)

环境: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 文件中的某些内容并希望将更改应用于所有内容而无需清除浏览器缓存。

一个重要的注意事项 如果您在开头添加带有斜杠的静态文件,您可能会遇到此处描述的问题“缺少...的静态文件清单”。所以在你的模板中:

这会起作用

<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' %}');">

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