ValueError: отсутствует запись манифеста статических файлов для 'favicon.ico'

Я получаю ValueError при беге python manage.py test, Мой проект назван fellow_go и сейчас я работаю над приложением под названием pickup,

Обратите внимание, что эта ошибка добавлена ​​в сравнительно недавнем коммите в Django: Исправлено #24452 - Исправлена ​​корректность HashedFilesMixin с вложенными путями.,

======================================================================
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 файл:


Странно, никаких ошибок не возникает с 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

Пожалуйста, скажите мне, что не так с моим кодом.

16 ответов

Решение

Попробуйте запустить:

python manage.py collectstatic

Тест работает сейчас? Если так, это может быть конфигурация, вызывающая проблему:

STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

Связанные с:
/questions/38122506/komanda-collectstatic-zavershaetsya-neudachno-esli-vklyuchen-whitenoise/38122532#38122532

Ознакомьтесь с документацией по Django: https://docs.djangoproject.com/en/1.11/ref/contrib/staticfiles/

Просто поделитесь решением, которое у меня было для этой проблемы, на случай, если оно поможет кому-то еще.

Я случайно включил начальный "/" в некоторые статические URL-адреса, из-за чего они отсутствовали в манифесте.

Решением было заменить все экземпляры:

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

с

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

а потом все заработало нормально.

storage.ManifestStaticFilesStorage.manifest_strict

Добавление этого параметра в настройки теста работает в моем случае:

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

* Джанго 1.11

Если вы хотите продолжать использовать модуль WhiteNoise в своем проекте Django 1.11 (или новее), одновременно предотвращая ошибку "Missing staticfiles manifest entry", необходимо отключить manifest_strict атрибут с помощью наследования, как отмечено в документации Django.

Как это сделать?

Во-первых, создать storage.py файл в каталоге вашего проекта:

from whitenoise.storage import CompressedManifestStaticFilesStorage


class WhiteNoiseStaticFilesStorage(CompressedManifestStaticFilesStorage):
    manifest_strict = False

Во-вторых, отредактируйте STATICFILES_STORAGE постоянная в вашем settings.py файл, указывающий на этот новый класс, такой как:

STATICFILES_STORAGE = 'my_project.storage.WhiteNoiseStaticFilesStorage'

Django вызывает это исключение, если вы ссылаетесь на статический файл во время тестов, но не запускали ./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'
)

В последней версии Whitenoise (в настоящее время 5.2) теперь вы можете делать..

WHITENOISE_MANIFEST_STRICT = False

У меня была такая же проблема; где я получал «Отсутствует запись в манифесте статических файлов» каждый раз, когда я запускал свой сервер с DEBUG = False.

Мне потребовалось много часов, чтобы понять, что проблема заключалась в включении символа "/" в начале моих статических ссылок.

Например:{% static '/app/styles/main.css'%} вместо {% static 'app / styles / main.css'%}.

Актуальное решение можно найти здесь

Проблема в том, что Django на самом деле не знает, где находится статический файл, и когда вы
это делаете, он на самом деле не копирует его вам.STATIC_ROOT

Решение

  1. вручную попробуйте найти статические файлы, используяpython manage.py findstatic <your static files>

    вам нужно сделать это для каждого статического файла. если эта команда не сработала, это означает, что Django не может найти ваши статические файлы. Чтобы решить эту проблему, вам нужно определить путь к статическим файлам внутри вашего
    STATIC_DIRSвнутри ваших настроек.py

пример

      STATIC_DIRS = [
   os.path.join(BASE_DIR, "path/to/your/staticfiles")
]
  1. определять
      STATIC_ROOT = "staticfiles"
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
  1. делатьpython manage.py collectstatic
    и после этого он должен работать

У меня это в моем settings.py

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

после того, как я удалил блок try, все снова заработало.

env: Python 3.8, Django 3.1.5

В основном я не использую отбеливатель. На мой взгляд, класс ManifestStaticFilesStorage от Django отлично справляется со сбором статических файлов. Он добавляет уникальный хэш, работает быстро и не требует никаких других зависимостей.

На рабочем сервере (где статические файлы обслуживаются 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. Он также создаст копию каждого файла с уникальным идентификатором и создаст 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' %}');">

Это небольшая разница, но вы должны ее запомнить. Надеюсь, это будет полезно :)

In my case this was occurring because I am using nginx (Docker) to serve the static images. This is occurring when the app is running, not during testing like the OP.

The issue was that I was declaring the STATIC_ROOT to be outside of the Django app:

STATIC_ROOT = "../staticfiles"

I did this so that the assets were not unnecessarily copied onto the Django container. This works fine if you use the default STATICFILES_STORAGE, but when using ManifestStaticFilesStorage, the static file lookup fails because it cannot find manifest file asset in directory on the Django container.

The solution is simply to declare static files to be present on the Django image:

STATIC_ROOT = "staticfiles"

This does create to copies of the static files: one copy on the nginx container, and one on Django, but it means that the Django lookup logic succeeds, even though the files are served from nginx.

Another option would be to disable the manifest_strict attribute:

storage.ManifestStaticFilesStorage.manifest_strict

Если файл не найден в манифесте staticfiles.json во время выполнения, возникает ошибка ValueError. Это поведение можно отключить, создав подкласс ManifestStaticFilesStorage и установив для атрибута manifest_strict значение False - несуществующие пути останутся неизменными.

У меня была такая же проблема, и я исправил ее, изменив STATICFILES_STORAGE кому:

STATICFILES_STORAGE = 'cloudinary_storage.storage.StaticHashedCloudinaryStorage'

Затем следует запустить:

python manage.py collectstatic

Этот ответ помог мне решить эту проблему.

Сначала добавьте это в 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,
    },
}}

А затем добавьте это в конец вашего settings.py, если вы используете django-heroku:

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

Вот обновленный ответ для тех, кто использует Whitenoise вместе с Django >= 4.2:

      # settings.py
STORAGES = {
    "default": {
        "BACKEND": "django.core.files.storage.FileSystemStorage",
    },
    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"
        if not TESTING
        else "whitenoise.storage.CompressedStaticFilesStorage",
        # disables the caching behavior for the tests, for static files to load properly
    },
}

Этот новыйSTORAGESЭтот параметр упоминается в этом примечании к выпуску и здесь , в документации Django.

Документация Whitenoise также была обновлена, как вы можете видеть здесь .

В моем случае я не уверен, почему это происходит, но после того, как я удалил heroku настройки django_heroku.settings(locals()) все снова заработало.

Для меня проблема заключалась в том, что в одном месте я имел в виду папку, изображения, как{% static 'images' %}. Изменение этого на{% static 'images/' %}, с косой чертой в конце, решил проблему. Сногсшибательно.

Другие вопросы по тегам