Commit b41afa61 by ara818

Merge branch 'master' of git://github.com/paltman/django-compress

parents 4eecb627 bef9a80e
......@@ -2,6 +2,9 @@ from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
COMPRESS = getattr(settings, 'COMPRESS', not settings.DEBUG)
COMPRESS_SOURCE = getattr(settings, 'COMPRESS_SOURCE', settings.MEDIA_ROOT)
COMPRESS_ROOT = getattr(settings, 'COMPRESS_ROOT', settings.MEDIA_ROOT)
COMPRESS_URL = getattr(settings, 'COMPRESS_URL', settings.MEDIA_URL)
COMPRESS_AUTO = getattr(settings, 'COMPRESS_AUTO', True)
COMPRESS_VERSION = getattr(settings, 'COMPRESS_VERSION', False)
COMPRESS_VERSION_PLACEHOLDER = getattr(settings, 'COMPRESS_VERSION_PLACEHOLDER', '?')
......
from django.conf import settings
from compress.filter_base import FilterBase, FilterError
REPLACE_LIST = getattr(settings, 'COMPRESS_CSS_URL_REPLACE', [])
class CSSURLReplace(FilterBase):
def filter_css(self, css):
filtered_css = css
if type(REPLACE_LIST) == list:
for REPLACE in REPLACE_LIST:
if len(REPLACE) == 2:
filtered_css = filtered_css.replace(REPLACE[0], REPLACE[1])
if self.verbose:
print 'Replaced "%s" with "%s"' % REPLACE
return filtered_css
\ No newline at end of file
......@@ -34,8 +34,11 @@ class Command(NoArgsCommand):
print
for name, js in settings.COMPRESS_JS.items():
u, version = needs_update(js['output_filename'],
js['source_filenames'])
if 'external_urls' in js:
u, version = False, "External"
else:
u, version = needs_update(js['output_filename'],
js['source_filenames'])
if (force or u) or verbosity >= 2:
msg = 'JavaScript Group \'%s\'' % name
......@@ -43,7 +46,7 @@ class Command(NoArgsCommand):
print len(msg) * '-'
print "Version: %s" % version
if force or u:
if (force or u) and 'external_urls' not in js:
filter_js(js, verbosity)
if (force or u) or verbosity >= 2:
......
......@@ -5,7 +5,7 @@ from django import template
from django.conf import settings as django_settings
from compress.conf import settings
from compress.utils import media_root, media_url, needs_update, filter_css, filter_js, get_output_filename, get_version, get_version_from_file
from compress.utils import compress_root, compress_url, needs_update, filter_css, filter_js, get_output_filename, get_version, get_version_from_file
register = template.Library()
......@@ -18,7 +18,7 @@ def render_common(template_name, obj, filename, version):
if filename.startswith('http://'):
context['url'] = filename
else:
context['url'] = media_url(filename, prefix)
context['url'] = compress_url(filename, prefix)
return template.loader.render_to_string(template_name, context)
......@@ -49,9 +49,9 @@ class CompressedCSSNode(template.Node):
css['source_filenames'])
if u:
filter_css(css)
else:
elif not css.get('extra_context', {}).get('prefix', None):
filename_base, filename = os.path.split(css['output_filename'])
path_name = media_root(filename_base)
path_name = compress_root(filename_base)
version = get_version_from_file(path_name, filename)
return render_css(css, css['output_filename'], version)
......@@ -90,9 +90,9 @@ class CompressedJSNode(template.Node):
js['source_filenames'])
if u:
filter_js(js)
else:
elif not js.get('extra_context', {}).get('prefix', None):
filename_base, filename = os.path.split(js['output_filename'])
path_name = media_root(filename_base)
path_name = compress_root(filename_base)
version = get_version_from_file(path_name, filename)
return render_js(js, js['output_filename'], version)
......
......@@ -46,7 +46,7 @@ def needs_update(output_file, source_files, verbosity=0):
version = get_version(source_files)
on = get_output_filename(output_file, version)
compressed_file_full = media_root(on)
compressed_file_full = compress_root(on)
if not os.path.exists(compressed_file_full):
return True, version
......@@ -54,16 +54,22 @@ def needs_update(output_file, source_files, verbosity=0):
update_needed = getattr(get_class(settings.COMPRESS_VERSIONING)(), 'needs_update')(output_file, source_files, version)
return update_needed
def media_root(filename):
def compress_root(filename):
"""
Return the full path to ``filename``. ``filename`` is a relative path name in MEDIA_ROOT
Return the full path to ``filename``. ``filename`` is a relative path name in COMPRESS_ROOT
"""
return os.path.join(django_settings.MEDIA_ROOT, filename)
return os.path.join(settings.COMPRESS_ROOT, filename)
def media_url(url, prefix=None):
def compress_source(filename):
"""
Return the full path to ``filename``. ``filename`` is a relative path name in COMPRESS_SOURCE
"""
return os.path.join(settings.COMPRESS_SOURCE, filename)
def compress_url(url, prefix=None):
if prefix:
return prefix + urlquote(url)
return django_settings.MEDIA_URL + urlquote(url)
return settings.COMPRESS_URL + urlquote(url)
def concat(filenames, separator=''):
"""
......@@ -71,20 +77,17 @@ def concat(filenames, separator=''):
"""
r = ''
for filename in filenames:
fd = open(media_root(filename), 'rb')
fd = open(compress_source(filename), 'rb')
r += fd.read()
r += separator
fd.close()
return r
def max_mtime(files):
return int(max([os.stat(media_root(f)).st_mtime for f in files]))
def save_file(filename, contents):
dirname = os.path.dirname(media_root(filename))
dirname = os.path.dirname(compress_root(filename))
if not os.path.exists(dirname):
os.makedirs(dirname)
fd = open(media_root(filename), 'wb+')
fd = open(compress_root(filename), 'wb+')
fd.write(contents)
fd.close()
......@@ -121,7 +124,7 @@ def filter_common(obj, verbosity, filters, attr, separator, signal):
filename = get_output_filename(obj['output_filename'], get_version(obj['source_filenames']))
if settings.COMPRESS_VERSION:
remove_files(os.path.dirname(media_root(filename)), obj['output_filename'], verbosity)
remove_files(os.path.dirname(compress_root(filename)), obj['output_filename'], verbosity)
if verbosity >= 1:
print "Saving %s" % filename
......
import os
from compress.utils import get_output_filename, media_root
from compress.utils import get_output_filename, compress_source, compress_root
from compress.versioning.base import VersioningBase
class MTimeVersioning(VersioningBase):
......@@ -8,12 +8,13 @@ class MTimeVersioning(VersioningBase):
def get_version(self, source_files):
# Return the modification time for the newest source file
return str(max([int(os.stat(media_root(f)).st_mtime) for f in source_files]))
return str(max(
[int(os.stat(compress_source(f)).st_mtime) for f in source_files]))
def needs_update(self, output_file, source_files, version):
output_file_name = get_output_filename(output_file, version)
compressed_file_full = media_root(output_file_name)
compressed_file_full = compress_root(output_file_name)
return (int(os.stat(compressed_file_full).st_mtime) < int(version)), version
......@@ -85,6 +85,46 @@ Network, you can use the optional _prefix_ parameter:
In this example, the template tags will render _http://cdn.example.com/css/one_compressed.css_ in the link tag. You will need to manually put there after you build as part of your deployment process.
h4. CSS URL Replace Filter
This is a really simple filter for doing Python string replacements on your CSS. The use case for this is when you have root relative
urls defined in your css:
<pre><code>
body {background-image:url(/media/images/background.gif);}
</code></pre>
If you are compiling your media to live on another server, for example if you are deploying the compiled resources to Amazon S3, these
root relative urls will break. That is of course unless you also deploy all the media so they stay relative. However, then you limit yourself
from being able to prefix the source with a date or version number. Ideally, you should be able to control where the images are deployed
and those might be different from where your js/css media are being served from.
This filter offers a very simple solution. Really too simple. One could make the argument for just doing this search and replace manually
after the fact, however, I like for my build process to be as automated as possible. Therefore, I want to write down the rules/settings
once and be able to repeat the build process when needed without thinking about the find and replace.
Enough babbling, here is an example settings.py section:
<pre><code>
COMPRESS_CSS_FILTERS = ('compress.filters.yui.YUICompressorFilter', 'compress.filters.css_url_replace.CSSURLReplace')
URL_REPLACE_HOST = 'http://localhost:8000'
COMPRESS_CSS_URL_REPLACE = [("url(/media", "url(%s/media" % URL_REPLACE_HOST),]
</code></pre>
This will run the CSSURLReplace filter after the CSS is compressed (it is safe to do this in any order, at least for this filter). The URL_REPLACE_HOST
is not required, just a variable I defined in my settings file to keep things clean (and to override in other environments -- this is obviously my dev
settings file).
The COMPRESS_CSS_URL_REPLACE is the only required setting by this filter. It takes a list of tuples, each tuple being exactly two strings.
The first argument in each tuple is the string to find, and the second is the string to replace it with. The replace operations will execute
in the order they are inserted into the list. Here I am replacing all url(/media....) in my compiled css to an absolute url of url(http://localhost:8000/media...).
This will have the result of my compiled css can be hosted anywhere and the images will still be served off of http://localhost:8000 (or anywhere else
that I define in URL_REPLACE_HOST prior to build).
You could obviously use this filter to do other types of replacements.
h4. External urls
While django-compress does a great job of minimizing the amount of http requests on your site (hence increasing performence) there are sometimes cases
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment