Permalink
Browse files

Stop hard-error on file-not-found; add resolution for shared assets (…

…things in Static) in the Python apps
  • Loading branch information...
1 parent 89bd3ea commit f33ce7f71cbe916d0b00151bbf9d7c2a31796dfb @fidothe fidothe committed Apr 18, 2011
View
@@ -41,15 +41,20 @@ in `settings.py` add cdn_helpers to your list of installed apps:
'cdn_helpers'
)
+in your local-development `local_settings.py`:
+
+ APP_DEPLOYMENT_ENV = 'local' # (disables CDN url generation)
+ CDN_HOSTS = []
+
in the appropriate `local_settings.py`:
APP_DEPLOYMENT_ENV = 'dev' # (or staging, production)
CDN_HOSTS = ['cdn1', 'cdn2'] # (as appropriate for the environment)
-
+ SHARED_PUBLIC_ROOT = "/path/to/shared/assets" # (i.e. where Static's public dir is)
in templates use the `asset_url` helper:
<img src="{% asset_url "/images/thing.png" %}">
- <img src="{% asset_url thing.image.src %}">
+ <img src="{% asset_url thing.image.url %}">
The app provides the `cdn_css` command for `manage.py`. This uses the Ruby script process_css to do the heavy lifting, but relies on the `MEDIA_ROOT` and `MEDIA_URL` settings in `settings.py` to tell where to look and how to construct the URLs.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -25,8 +25,10 @@ def __init__(self, settings = None):
def process_url(self, url):
"""Process url and return a suitable URL for the app's environment"""
if hasattr(self.settings, 'APP_DEPLOYMENT_ENV') and self.settings.APP_DEPLOYMENT_ENV != 'local':
- sha1 = self.generate_sha1(self.file_path_from_url(url))
- return self.compose_url(url, sha1)
+ sha1 = self.fetch_sha1(self.file_path_from_url(url), self.generate_sha1)
+ if sha1 != None:
+ url = self.compose_path(url, sha1)
+ return self.compose_url(url)
else:
return url
@@ -36,22 +38,34 @@ def file_path_from_url(self, url):
media_url = '%s/' % self.settings.MEDIA_URL.lstrip('/').rstrip('/')
if stripped_url.find(media_url) == 0:
url = stripped_url[len(media_url) - 1:]
- return os.path.normpath(os.path.join(self.settings.MEDIA_ROOT, url.lstrip('/')))
+ local_path = os.path.normpath(os.path.join(self.settings.MEDIA_ROOT, url.lstrip('/')))
+ if os.path.exists(local_path):
+ return local_path
+ if hasattr(self.settings, 'SHARED_PUBLIC_ROOT'):
+ shared_path = os.path.normpath(os.path.join(self.settings.SHARED_PUBLIC_ROOT, url.lstrip('/')))
+ if os.path.exists(shared_path):
+ return shared_path
+ return None
def generate_sha1(self, file_path):
"""Generates and return sha1 for the file at file_path"""
# import hashlib
+ if file_path == None:
+ return None
hash_func = hashlib.sha1()
with open(file_path) as f:
hash_func.update(f.read())
return hash_func.hexdigest()
+
+ def compose_path(self, path, sha1):
+ """Stitch path and hash together"""
+ return path + '/' + sha1[0:8] + os.path.splitext(path)[1]
- def compose_url(self, path, sha1):
- """Stitch path and hash together into a CDN url"""
+ def compose_url(self, uri_path):
+ """Stitch hashed path into a CDN url"""
# import random, os
host = random.choice(self.settings.CDN_HOSTS)
- uri_path = path + '/' + sha1[0:8] + os.path.splitext(path)[1]
return urlparse.urlunparse(('http', host, uri_path, '', '', ''))
def fetch_sha1(self, path, sha1_generator):
View
@@ -33,12 +33,18 @@ def test_sha1_calculation(self):
self.asset_url.generate_sha1(os.path.join(fixtures_dir, 'h5.png')),
'daf4a94f8d2cc9f564a6f958d1915ea9346d09f1'
)
+
+ def test_sha1_calculation_returns_None_if_passed_None(self):
+ self.assertEqual(
+ self.asset_url.generate_sha1(None),
+ None
+ )
def test_url_generation(self):
self.django_settings['CDN_HOSTS'] = ['dev1.host.com']
self.assertEqual(
- self.asset_url.compose_url('/images/h5.png', 'daf4a94f8d2cc9f564a6f958d1915ea9346d09f1'),
+ self.asset_url.compose_url('/images/h5.png/daf4a94f.png'),
'http://dev1.host.com/images/h5.png/daf4a94f.png'
)
@@ -85,6 +91,34 @@ def test_correctly_locates_a_file_when_media_url_is_set(self):
os.path.normpath(os.path.join(fixtures_dir, 'images/thing.png'))
)
+ def test_correctly_locates_a_shared_file_if_SHARED_PUBLIC_ROOT_is_set(self):
+ self.django_settings['MEDIA_ROOT'] = fixtures_dir
+ self.django_settings['MEDIA_URL'] = '/media_url/'
+ self.django_settings['SHARED_PUBLIC_ROOT'] = os.path.join(fixtures_dir, 'files_from_static')
+
+ self.assertEqual(
+ self.asset_url.file_path_from_url('/media_url/images/answers-advisory-highlight.png'),
+ os.path.normpath(os.path.join(fixtures_dir, 'files_from_static', 'images/answers-advisory-highlight.png'))
+ )
+
+ def test_returns_None_for_a_shared_file_if_SHARED_PUBLIC_ROOT_is_not_set(self):
+ self.django_settings['MEDIA_ROOT'] = fixtures_dir
+ self.django_settings['MEDIA_URL'] = '/media_url/'
+
+ self.assertEqual(
+ self.asset_url.file_path_from_url('/media_url/images/answers-advisory-highlight.png'),
+ None
+ )
+
+ def test_returns_None_if_file_cannot_be_located(self):
+ self.django_settings['MEDIA_ROOT'] = fixtures_dir
+ self.django_settings['MEDIA_URL'] = '/media_url/'
+
+ self.assertEqual(
+ self.asset_url.file_path_from_url('/media_url/unreal.css'),
+ None
+ )
+
class TestAssetUrlFromCDN(unittest.TestCase):
def setUp(self):
self.django_settings = MockSettings()
@@ -96,6 +130,12 @@ def test_cdn_url_created(self):
self.django_settings['CDN_HOSTS'] = ['cdn.host.com']
self.assertEqual(self.asset_url.process_url('/h5.png'), 'http://cdn.host.com/h5.png/daf4a94f.png')
+ def test_cdn_url_returns_unhashed_url_if_file_not_found(self):
+ self.django_settings['MEDIA_ROOT'] = fixtures_dir
+ self.django_settings['APP_DEPLOYMENT_ENV'] = 'dev'
+ self.django_settings['CDN_HOSTS'] = ['cdn.host.com']
+ self.assertEqual(self.asset_url.process_url('/h51.png'), 'http://cdn.host.com/h51.png')
+
if __name__ == '__main__':
unittest.main()

0 comments on commit f33ce7f

Please sign in to comment.