Skip to content

Instantly share code, notes, and snippets.

@kottenator
Last active July 6, 2016 20:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kottenator/fe4b0a05d1645af6986fbfdd407c57a7 to your computer and use it in GitHub Desktop.
Save kottenator/fe4b0a05d1645af6986fbfdd407c57a7 to your computer and use it in GitHub Desktop.
django-compressor - abstract static URL
"""
Django 'base' app - compressor filters.
"""
from compressor.filters.css_default import CssAbsoluteFilter
class CssRelativeFilter(CssAbsoluteFilter):
"""
``compressor.filters.css_default.CssAbsoluteFilter`` converts relative URLs to images, fonts, etc
in CSS code to absolute URLs like '/static/base/images/logo.svg'.
But STATIC_URL may change in different environments -
this is important for offline compression.
All compressed CSS files are served on URLs like '/static/CACHE/css/25b44215c797.css'.
So we can convert relative URLs inside '/static/CACHE/css/25b44215c797.css'
to '../../base/images/logo.svg' which works with _any_ STATIC_URL.
"""
def __init__(self, *args, **kwargs):
super(CssRelativeFilter, self).__init__(*args, **kwargs)
self.url = '../..'
"""
Django 'base' app - config.
"""
from functools import wraps
from compressor.management.commands.compress import Command
from compressor.templatetags.compress import CompressorNode
from django.apps.config import AppConfig
from django.conf import settings
class BaseConfig(AppConfig):
name = 'base'
STATIC_URL_PLACEHOLDER = '$STATIC_URL/'
def ready(self):
self._patch_compressor()
def _patch_compressor(self):
"""
Patch ``django-compressor`` to read/write offline manifest with STATIC_URL replaced
by special placeholder, because STATIC_URL may change in different environments.
"""
# Patch django-compressor offline manifest generator command
self._patch_compressor_method(Command, 'compress')
# Patch django-compressor offline manifest check
self._patch_compressor_method(
CompressorNode, 'render_offline', lambda r, u: r.replace(self.STATIC_URL_PLACEHOLDER, u)
)
def _patch_compressor_method(self, cls, name, post_process=None):
"""
Replace class method with patched one:
- substitute ``settings.STATIC_URL`` with special placeholder
- execute original method
- optionally, post-process method return value
- restore original ``settings.STATIC_URL`` value
:param type cls: Class object to patch
:param str name: Class method name
:param function post_process: Takes 2 arguments: method return value and static URL
"""
method = getattr(cls, name)
placeholder = self.STATIC_URL_PLACEHOLDER
if hasattr(method, '_original'):
return
@wraps(method)
def patched_method(self, *args, **kwargs):
static_url = settings.STATIC_URL
# TODO: some processing for settings.COMPRESS_URL needed
settings.STATIC_URL = settings.COMPRESS_URL = placeholder
try:
result = method(self, *args, **kwargs)
if post_process is not None:
result = post_process(result, static_url)
return result
finally:
# TODO: some processing for settings.COMPRESS_URL needed
settings.STATIC_URL = settings.COMPRESS_URL = static_url
patched_method._original = method
setattr(cls, name, patched_method)
INSTALLED_APPS = [
'base.conf.BaseConfig'
]
COMPRESS_CSS_FILTERS = [
'base.compressor_filters.CssRelativeFilter'
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment