mirror of https://github.com/django/django.git
Fixed #18050 -- Fixed a rather glaring bug in the handling of @import statements when using the cached staticfiles storage.
This commit is contained in:
parent
effc2cad95
commit
3047981517
|
@ -45,10 +45,11 @@ class StaticFilesStorage(FileSystemStorage):
|
||||||
|
|
||||||
|
|
||||||
class CachedFilesMixin(object):
|
class CachedFilesMixin(object):
|
||||||
|
default_template = """url("%s")"""
|
||||||
patterns = (
|
patterns = (
|
||||||
("*.css", (
|
("*.css", (
|
||||||
br"""(url\(['"]{0,1}\s*(.*?)["']{0,1}\))""",
|
br"""(url\(['"]{0,1}\s*(.*?)["']{0,1}\))""",
|
||||||
br"""(@import\s*["']\s*(.*?)["'])""",
|
(br"""(@import\s*["']\s*(.*?)["'])""", """@import url("%s")"""),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -62,8 +63,12 @@ class CachedFilesMixin(object):
|
||||||
self._patterns = SortedDict()
|
self._patterns = SortedDict()
|
||||||
for extension, patterns in self.patterns:
|
for extension, patterns in self.patterns:
|
||||||
for pattern in patterns:
|
for pattern in patterns:
|
||||||
|
if isinstance(pattern, (tuple, list)):
|
||||||
|
pattern, template = pattern
|
||||||
|
else:
|
||||||
|
template = self.default_template
|
||||||
compiled = re.compile(pattern)
|
compiled = re.compile(pattern)
|
||||||
self._patterns.setdefault(extension, []).append(compiled)
|
self._patterns.setdefault(extension, []).append((compiled, template))
|
||||||
|
|
||||||
def file_hash(self, name, content=None):
|
def file_hash(self, name, content=None):
|
||||||
"""
|
"""
|
||||||
|
@ -140,10 +145,13 @@ class CachedFilesMixin(object):
|
||||||
|
|
||||||
return unquote(final_url)
|
return unquote(final_url)
|
||||||
|
|
||||||
def url_converter(self, name):
|
def url_converter(self, name, template=None):
|
||||||
"""
|
"""
|
||||||
Returns the custom URL converter for the given file name.
|
Returns the custom URL converter for the given file name.
|
||||||
"""
|
"""
|
||||||
|
if template is None:
|
||||||
|
template = self.default_template
|
||||||
|
|
||||||
def converter(matchobj):
|
def converter(matchobj):
|
||||||
"""
|
"""
|
||||||
Converts the matched URL depending on the parent level (`..`)
|
Converts the matched URL depending on the parent level (`..`)
|
||||||
|
@ -178,7 +186,8 @@ class CachedFilesMixin(object):
|
||||||
relative_url = '/'.join(url.split('/')[:-1] + file_name)
|
relative_url = '/'.join(url.split('/')[:-1] + file_name)
|
||||||
|
|
||||||
# Return the hashed version to the file
|
# Return the hashed version to the file
|
||||||
return 'url("%s")' % unquote(relative_url)
|
return template % unquote(relative_url)
|
||||||
|
|
||||||
return converter
|
return converter
|
||||||
|
|
||||||
def post_process(self, paths, dry_run=False, **options):
|
def post_process(self, paths, dry_run=False, **options):
|
||||||
|
@ -229,9 +238,9 @@ class CachedFilesMixin(object):
|
||||||
# ..to apply each replacement pattern to the content
|
# ..to apply each replacement pattern to the content
|
||||||
if name in adjustable_paths:
|
if name in adjustable_paths:
|
||||||
content = original_file.read().decode(settings.FILE_CHARSET)
|
content = original_file.read().decode(settings.FILE_CHARSET)
|
||||||
converter = self.url_converter(name)
|
|
||||||
for patterns in self._patterns.values():
|
for patterns in self._patterns.values():
|
||||||
for pattern in patterns:
|
for pattern, template in patterns:
|
||||||
|
converter = self.url_converter(name, template)
|
||||||
content = pattern.sub(converter, content)
|
content = pattern.sub(converter, content)
|
||||||
if hashed_file_exists:
|
if hashed_file_exists:
|
||||||
self.delete(hashed_name)
|
self.delete(hashed_name)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
@import 'styles.css';
|
|
@ -446,6 +446,13 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
|
||||||
self.assertIn(b'url("img/relative.acae32e4532b.png")', content)
|
self.assertIn(b'url("img/relative.acae32e4532b.png")', content)
|
||||||
self.assertIn(b"../cached/styles.93b1147e8552.css", content)
|
self.assertIn(b"../cached/styles.93b1147e8552.css", content)
|
||||||
|
|
||||||
|
def test_import_replacement(self):
|
||||||
|
"See #18050"
|
||||||
|
relpath = self.cached_file_path("cached/import.css")
|
||||||
|
self.assertEqual(relpath, "cached/import.2b1d40b0bbd4.css")
|
||||||
|
with storage.staticfiles_storage.open(relpath) as relfile:
|
||||||
|
self.assertIn(b"""import url("styles.93b1147e8552.css")""", relfile.read())
|
||||||
|
|
||||||
def test_template_tag_deep_relative(self):
|
def test_template_tag_deep_relative(self):
|
||||||
relpath = self.cached_file_path("cached/css/window.css")
|
relpath = self.cached_file_path("cached/css/window.css")
|
||||||
self.assertEqual(relpath, "cached/css/window.9db38d5169f3.css")
|
self.assertEqual(relpath, "cached/css/window.9db38d5169f3.css")
|
||||||
|
|
Loading…
Reference in New Issue