﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
31520	ManifestStaticFilesStorage should not raise ValueError on missing file when manifest_strict=False	thenewguy	thenewguy	"I am using ManifestStaticFilesStorage and was under the impression that subclassing and setting `manifest_strict=False` would allow pages to render if a static file is missing (perhaps due to a template typo) instead of raising a ValueError.

However, if the file is missing from disk a ValueError is raised.

I believe this is an oversight as it would be preferrable for a typo to cause a 404 instead of preventing a page from rendering.

Adding this try/except block lets the page render and the tests below pass.  Otherwise they fail when the files do not exist.


{{{

        if cache_name is None:
            if self.manifest_strict:
                raise ValueError(""Missing staticfiles manifest entry for '%s'"" % clean_name)
            try:
                hashed = self.hashed_name(name)
            except ValueError:
                hashed = name
            cache_name = self.clean_name(hashed)

}}}


This is what the reworked function looks like:


{{{
    def stored_name(self, name):
        parsed_name = urlsplit(unquote(name))
        clean_name = parsed_name.path.strip()
        hash_key = self.hash_key(clean_name)
        cache_name = self.hashed_files.get(hash_key)
        if cache_name is None:
            if self.manifest_strict:
                raise ValueError(""Missing staticfiles manifest entry for '%s'"" % clean_name)
            try:
                hashed = self.hashed_name(name)
            except ValueError:
                hashed = name
            cache_name = self.clean_name(hashed)
        unparsed_name = list(parsed_name)
        unparsed_name[2] = cache_name
        # Special casing for a @font-face hack, like url(myfont.eot?#iefix"")
        # http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax
        if '?#' in name and not unparsed_name[3]:
            unparsed_name[2] += '?'
        return urlunsplit(unparsed_name)
}}}


And here are the tests:

{{{
from os.path import exists

from django.conf import settings
from django.templatetags.static import static
from django.test import SimpleTestCase, override_settings


@override_settings(STATIC_URL='/static/')
class StaticResolveTest(SimpleTestCase):
    def test_existing_static_path_resolves(self):
        location = 'admin/js/vendor/jquery/jquery.js'
        path = join(settings.STATIC_ROOT, location)
        self.assertTrue(exists(path), 'Path ""%s"" did not exist' % path)
        
        static_location = static(location)
        static_location_parts = static_location.split('.')
        self.assertEqual(static_location_parts[0], '/static/admin/js/vendor/jquery/jquery')
        self.assertEqual(static_location_parts[-1], 'js')
    
    def test_missing_static_path_resolves(self):
        location = 'does-not-exist.txt'
        path = join(settings.STATIC_ROOT, location)
        self.assertFalse(exists(path), 'Path ""%s"" was not supposed to exist' % path)
        self.assertEqual(static(location), '/static/does-not-exist.txt')

    def test_served_static_response(self):
        location = 'admin/js/vendor/jquery/jquery.js'
        path = join(settings.STATIC_ROOT, location)
        self.assertTrue(exists(path), 'Path ""%s"" did not exist' % path)
        
        response = self.client.get(static(location))
        self.assertEqual(response.status_code, 200)
        
        self.assertTrue(response.streaming)
        response_content = b''.join(response.streaming_content)
        with open(path, 'rb') as fp:
            disk_content = fp.read()
        self.assertEqual(response_content, disk_content)
    
    def test_missing_static_response(self):
        location = 'does-not-exist.txt'
        path = join(settings.STATIC_ROOT, location)
        self.assertFalse(exists(path), 'Path ""%s"" was not supposed to exist' % path)
        
        response = self.client.get(static(location))
        self.assertEqual(response.status_code, 404)

}}}
"	New feature	closed	contrib.staticfiles	3.0	Normal	wontfix			Unreviewed	0	0	0	0	0	0
