Skip to content

Conversation

fkoester
Copy link

The behaviour of ManifestStaticFilesStorage differs between debug and
non-debug mode when a referenced static file does not actually exist (or an
absolute path is used instead of a relative one).

The following code demonstrates the issue:

from django.contrib.staticfiles.storage import ManifestStaticFilesStorage
>>> ManifestStaticFilesStorage().url("path/to/a/file.png")
'/static/path/to/a/file.png'
>>> ManifestStaticFilesStorage().url("/path/to/a/file.png")
'/static/path/to/a/file.png'
>>> ManifestStaticFilesStorage().url("path/to/a/file.png", force=True)
'/static/path/to/a/file.f208556b8835.png'
>>> ManifestStaticFilesStorage().url("/path/to/a/file.png", force=True)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    ManifestStaticFilesStorage().url('/path/to/a/file.png', force=True)
  File "/app/.pyenv/versions/3.7.2/lib/python3.7/site-packages/django/contrib/staticfiles/storage.py", line 153, in url
    return self._url(self.stored_name, name, force)
  File "/app/.pyenv/versions/3.7.2/lib/python3.7/site-packages/django/contrib/staticfiles/storage.py", line 132, in _url
    hashed_name = hashed_name_func(*args)
  File "/app/.pyenv/versions/3.7.2/lib/python3.7/site-packages/django/contrib/staticfiles/storage.py", line 420, in stored_name
    raise ValueError("Missing staticfiles manifest entry for '%s'" % clean_name)
ValueError: Missing staticfiles manifest entry for '/path/to/a/file.png'

The root cause for the issue is that when the staticfiles are hashed Django puts
them into the manifest file ("staticfiles.json") with a relative path (i.e.
without a leading slash) and when trying to find the file with leading slash
it fails because it does not exist. When getting the URL in debug mode it just
joins the path to the STATIC_URL (in our case /static) and we get the valid
url /static/path/to/a/file.png so no error is being raised.

This can cause trouble when all test systems are using debug = True and an
incorrect static file path is only detected after deployment to the production
instance that uses debug = False.

In order to fix the problem we should also check in debug mode whether the
referenced file really exists.

https://code.djangoproject.com/ticket/32131#ticket

The behaviour of `ManifestStaticFilesStorage` differs between debug and
non-debug mode when a referenced static file does not actually exist (or an
absolute path is used instead of a relative one).

The following code demonstrates the issue:

```
from django.contrib.staticfiles.storage import ManifestStaticFilesStorage
>>> ManifestStaticFilesStorage().url("path/to/a/file.png")
'/static/path/to/a/file.png'
>>> ManifestStaticFilesStorage().url("/path/to/a/file.png")
'/static/path/to/a/file.png'
>>> ManifestStaticFilesStorage().url("path/to/a/file.png", force=True)
'/static/path/to/a/file.f208556b8835.png'
>>> ManifestStaticFilesStorage().url("/path/to/a/file.png", force=True)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    ManifestStaticFilesStorage().url('/path/to/a/file.png', force=True)
  File "/app/.pyenv/versions/3.7.2/lib/python3.7/site-packages/django/contrib/staticfiles/storage.py", line 153, in url
    return self._url(self.stored_name, name, force)
  File "/app/.pyenv/versions/3.7.2/lib/python3.7/site-packages/django/contrib/staticfiles/storage.py", line 132, in _url
    hashed_name = hashed_name_func(*args)
  File "/app/.pyenv/versions/3.7.2/lib/python3.7/site-packages/django/contrib/staticfiles/storage.py", line 420, in stored_name
    raise ValueError("Missing staticfiles manifest entry for '%s'" % clean_name)
ValueError: Missing staticfiles manifest entry for '/path/to/a/file.png'
```

The root cause for the issue is that when the staticfiles are hashed Django puts
them into the manifest file ("staticfiles.json") with a relative path (i.e.
*without* a leading slash) and when trying to find the file *with* leading slash
it fails because it does not exist. When getting the URL in debug mode it just
joins the path to the `STATIC_URL` (in our case `/static`) and we get the valid
url `/static/path/to/a/file.png` so no error is being raised.

This can cause trouble when all test systems are using `debug = True` and an
incorrect static file path is only detected after deployment to the production
instance that uses `debug = False`.

In order to fix the problem we should also check in debug mode whether the
referenced file really exists.

https://code.djangoproject.com/ticket/32131#ticket
@carltongibson
Copy link
Member

Closing as per ticket. (Would need tests and docs.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants