To be released

  • Officially support Python 3.12 (requires lxml 4.9.3 or higher)

v4.4 (2023-06-28)

Full list of changes from v4.3.1

  • Officially support Django 4.2

v4.3.1 (2023-01-22)

Full list of changes from v4.3

  • Documentation fixes only

v4.3 (2023-01-06)

Full list of changes from v4.2

  • Officially support Python 3.11

v4.2 (2023-01-06)

Full list of changes from v4.1

  • Drop Python 3.6 and 3.7 support

  • Drop Django 2.2 and 3.1 support

  • Drop SlimItFilter

  • Update the CachedS3Boto3Storage example storage subclass in “Remote Storages” to work properly after the v4.0 change to how duplicate file names are handled by CompressorFileStorage

  • Update rsmin and jsmin versions

v4.1 (2022-08-03)

Full list of changes from v4.0

  • Add Django 4.1 compatibility

  • New setting COMPRESS_OFFLINE_MANIFEST_STORAGE to customize the offline manifest’s file storage (#1112)

    With this change the function compressor.cache.get_offline_manifest_filename() has been removed. You can now use the new file storage to access the location of the manifest.

v4.0 (2022-03-23)

Full list of changes from v3.1

  • Fix intermittent No such file or directory errors by changing strategy to deal with duplicate filenames in CompressorFileStorage

    Note: if your project has a custom storage backend following the example of CachedS3Boto3Storage from the “Remote Storages” documentation, it will need to be updated to call save instead of _save to work properly after this change to CompressorFileStorage.

  • Deprecate SlimItFilter, stop testing it with Python 3.7 or higher

v3.1 (2021-12-18)

Full list of changes from v3.0

  • Fix error with verbose offline compression when COMPRESS_OFFLINE_CONTEXT is a generator

v3.0 (2021-12-12)

Full list of changes from v2.4.1

  • Officially support Python 3.9 and 3.10 as well as Django 3.1, 3.2 and 4.0

  • Drop support for Django 1.11, 2.1 and 3.0

  • Drop support for Python 2.x and 3.4

  • Fix compatibility with Jinja 3.x

  • Require django-sekizai 2.0 for django-sekizai extension

  • Make template compression in compress command threaded to improve performance

  • Correctly handle relative paths in extends tags (#979)

  • Enable rCSSMinFilter by default (#888)

  • Fix various deprecation warnings

  • Add ability to pass a logger to various classes & methods

  • Removed deprecated COMPRESS_JS_FILTERS and COMPRESS_CSS_FILTERS settings

  • Fix offline compression race condition, which could result in incomplete manifest

v2.4.1 (2021-04-17)

Full list of changes from v2.4

  • Raise proper DeprecationWarning for COMPRESS_JS_FILTERS and COMPRESS_CSS_FILTERS

v2.4 (2019-12-31)

Full list of changes from v2.3

  • Add support for Django 3.0 (#950, #967)

  • Officially support Python 3.8 (#967)

  • Add better support for JS strict mode and validation (#952)

  • Add support for rel=preload (#951)

  • Add support for Calmjs (#957)

Note: in 2.3, a new setting COMPRESS_FILTERS has been introduced that combines the existing COMPRESS_CSS_FILTERS and COMPRESS_JS_FILTERS. The latter are now deprecated. See the docs on how to use the new setting, the conversion is straightforward.

v2.3 (2019-05-31)

Full list of changes from v2.2

  • Drop support for Django 1.8, 1.9 and 1.10

  • Add support for Django 2.1 and 2.2, as well as Python 3.7

  • Update all dependencies. This required minor code changes, you might need to update some optional dependencies if you use any

  • Allow the mixed use of JS/CSS in Sekizai’s templatetags {% addtoblock "js" %} and {% addtoblock "css" %} (#891)

  • Allow the implementation of new types other than css and js. (#900)

  • Update jinja2 extension to behave similar to the django tag (#899)

  • Fix crash in offline compression when child nodelist is None, again (#605)

  • Support STATIC_URL and COMPRESS_URL being string-like objects

  • Improve compress command memory usage (#870)

  • Ensure generated file always contains a base name (#775)

  • Add BrotliCompressorFileStorage (#867)

v2.2 (2017-08-16)

Full list of changes from v2.1.1

  • Switch from MD5 to SHA256 for hashes generation.

  • Add Django 1.11 compatibility

  • Various compatibility fixes for Python 3.6 and Django 1.8

  • Made OfflineGenerationError easier to debug

  • Drop support for Python 3.2

  • Add new CssRelativeFilter which works like CssAbsoluteFilter but outputs relative URLs.

  • Fix URL CssAbsoluteFilter URL detection

v2.1.1 (2017-02-02)

Full list of changes from v2.1

  • Fix to file permissions issue with packaging.

v2.1 (2016-08-09)

Full list of changes from v2.0

  • Add Django 1.10 compatibility

  • Add support for inheritance using a variable in offline compression

  • Fix recursion error with offline compression when extending templates with the same name

  • Fix UnicodeDecodeError when using CompilerFilter and caching

  • Fix CssAbsoluteFilter changing double quotes to single quotes, breaking SVG

v2.0 (2016-01-07)

Full list of changes from v1.6

  • Add Django 1.9 compatibility

  • Remove official support for Django 1.4 and 1.7

  • Add official support for Python 3.5

  • Remove official support for Python 2.6

  • Remove support for coffin and jingo

  • Fix Jinja2 compatibility for Django 1.8+

  • Stop bundling vendored versions of rcssmin and rjsmin, make them proper dependencies

  • Remove support for CSSTidy

  • Remove support for beautifulsoup 3.

  • Replace cssmin by csscompressor (cssmin is still available for backwards-compatibility but points to rcssmin)

v1.6 (2015-11-19)

Full list of changes from v1.5

  • Upgrade rcssmin and rjsmin

  • Apply CssAbsoluteFilter to precompiled css even when compression is disabled

  • Add optional caching to CompilerFilter to avoid re-compiling unchanged files

  • Fix various deprecation warnings on Django 1.7 / 1.8

  • Fix TemplateFilter

  • Fix double-rendering bug with sekizai extension

  • Fix debug mode using destination directory instead of staticfiles finders first

  • Removed some silent exception catching in compress command

v1.5 (2015-03-27)

Full list of changes from v1.4

  • Fix compress command and run automated tests for Django 1.8

  • Fix Django 1.8 warnings

  • Handle TypeError from import_module

  • Fix reading UTF-8 files which have BOM

  • Fix incompatibility with Windows (shell_quote is not supported)

  • Run automated tests on Django 1.7

  • Ignore non-existent {{ block.super }} in offline compression instead of raising AttributeError

  • Support for clean-css

  • Fix link markup

  • Add support for COMPRESS_CSS_HASHING_METHOD = None

  • Remove compatibility with old ‘staticfiles’ app

  • In compress command, use get_template() instead of opening template files manually, fixing compatibility issues with custom template loaders

  • Fix FilterBase so that does not override self.type for subclasses if filter_type is not specified at init

  • Remove unnecessary filename and existence checks in CssAbsoluteFilter

v1.4 (2014-06-20)

  • Added Python 3 compatibility.

  • Added compatibility with Django 1.6.x and dropped support for Django 1.3.X.

  • Fixed compatibility with html5lib 1.0.

  • Added offline compression for Jinja2 with Jingo and Coffin integration.

  • Improved support for template inheritance in offline compression.

  • Made offline compression avoid compressing the same block multiple times.

  • Added a testenv target in the Makefile to make it easier to set up the test environment.

  • Allowed data-uri filter to handle external/protocol-relative references.

  • Made CssCompressor class easier to extend.

  • Added support for explicitly stating the block being ended.

  • Added rcssmin and updated rjsmin.

  • Removed implicit requirement on BeautifulSoup.

  • Made GzipCompressorFileStorage set access and modified times to the same time as the corresponding base file.

  • Defaulted to using django’s simplejson, if present.

  • Fixed CompilerFilter to always output Unicode strings.

  • Fixed windows line endings in offline compression.

v1.3 (2013-03-18)

  • Backward incompatible changes

    • Dropped support for Python 2.5. Removed any and walk compatibility functions in compressor.utils.

    • Removed compatibility with some old django settings:

      • COMPRESS_ROOT no longer uses MEDIA_ROOT if STATIC_ROOT is not defined. It expects STATIC_ROOT to be defined instead.

      • COMPRESS_URL no longer uses MEDIA_URL if STATIC_URL is not defined. It expects STATIC_URL to be defined instead.

      • COMPRESS_CACHE_BACKEND no longer uses CACHE_BACKEND and simply defaults to default.

  • Added precompiler class support. This enables you to write custom precompilers with Python logic in them instead of just relying on executables.

  • Made CssAbsoluteFilter smarter: it now handles URLs with hash fragments or querystring correctly. In addition, it now leaves alone fragment-only URLs.

  • Removed a fsync() call in CompilerFilter to improve performance. We already called self.infile.flush() so that call was not necessary.

  • Added an extension to provide django-sekizai support. See django-sekizai Support for more information.

  • Fixed a DeprecationWarning regarding the use of django.utils.hashcompat

  • Updated bundled to fix some JavaScript compression errors.


  • Added compatibility with Django 1.4 and dropped support for Django 1.2.X.

  • Added contributing docs. Be sure to check them out and start contributing!

  • Moved CI to Travis:

  • Introduced a new compressed context dictionary that is passed to the templates that are responsible for rendering the compressed snippets.

    This is a backwards-incompatible change if you’ve overridden any of the included templates:

    • compressor/css_file.html

    • compressor/css_inline.html

    • compressor/js_file.html

    • compressor/js_inline.html

    The variables passed to those templates have been namespaced in a dictionary, so it’s easy to fix your own templates.

    For example, the old compressor/js_file.html:

    <script type="text/javascript" src="{{ url }}"></script>

    The new compressor/js_file.html:

    <script type="text/javascript" src="{{ compressed.url }}"></script>
  • Removed old templates named compressor/css.html and compressor/js.html that were originally left for backwards compatibility. If you’ve overridden them, just rename them to compressor/css_file.html or compressor/js_file.html and make sure you’ve accounted for the backwards incompatible change of the template context mentioned above.

  • Reverted an unfortunate change to the YUI filter that prepended 'java -jar' to the binary name, which doesn’t always work, e.g. if the YUI compressor is shipped as a script like /usr/bin/yui-compressor.

  • Changed the sender parameter of the post_compress() signal to be either compressor.css.CssCompressor or compressor.js.JsCompressor for easier customization.

  • Correctly handle offline compressing files that are found in {% if %} template blocks.

  • Renamed the second option for the COMPRESS_CSS_HASHING_METHOD setting from 'hash' to 'content' to better describe what it does. The old name is also supported, as well as the default being 'mtime'.

  • Fixed CssAbsoluteFilter, src attributes in includes now get transformed.

  • Added a new hook to allow developers to completely bypass offline compression in CompressorNode subclasses: is_offline_compression_enabled.

  • Dropped versiontools from required dependencies again.


  • Fixed an installation issue related to versiontools.


  • Fixed a stupid ImportError bug introduced in 1.1.

  • Fixed Jinja2 docs of since JINJA2_EXTENSIONS expects a class, not a module.

  • Fixed a Windows bug with regard to file resolving with staticfiles finders.

  • Stopped a potential memory leak when memoizing the rendered output.

  • Fixed the integration between staticfiles (e.g. in Django <= 1.3.1) and compressor which prevents the collectstatic management command to work.


    Make sure to remove the path method of your custom remote storage class!


  • Made offline compression completely independent from cache (by writing a manifest.json file).

    You can now easily run the compress management command locally and transfer the COMPRESS_ROOT dir to your server.

  • Updated installation instructions to properly mention all dependencies, even those internally used.

  • Fixed a bug introduced in 1.0 which would prevent the proper deactivation of the compression in production.

  • Added a Jinja2 contrib extension.

  • Made sure the rel attribute of link tags can be mixed case.

  • Avoid overwriting context variables needed for compressor to work.

  • Stopped the compress management command to require model validation.

  • Added missing imports and fixed a few PEP 8 issues.


  • Fixed regression in compressor.utils.staticfiles compatibility module.


  • BACKWARDS-INCOMPATIBLE Stopped swallowing exceptions raised by rendering the template tag in production (DEBUG = False). This has the potential to breaking lots of apps but on the other hand will help find bugs.

  • BACKWARDS-INCOMPATIBLE The default function to create the cache key stopped containing the server hostname. Instead the cache key now only has the form 'django_compressor.<KEY>'.

    To revert to the previous way simply set the COMPRESS_CACHE_KEY_FUNCTION to 'compressor.cache.socket_cachekey'.

  • BACKWARDS-INCOMPATIBLE Renamed ambigously named COMPRESS_DATA_URI_MAX_SIZE setting to COMPRESS_DATA_URI_MAX_SIZE. It’s the maximum size the compressor.filters.datauri.DataUriFilter filter will embed files as data: URIs.

  • Added COMPRESS_CSS_HASHING_METHOD setting with the options 'mtime' (default) and 'hash' for the CssAbsoluteFilter filter. The latter uses the content of the file to calculate the cache-busting hash.

  • Added support for {{ block.super }} to compress management command.

  • Dropped Django 1.1.X support.

  • Fixed compiler filters on Windows.

  • Handle new-style cached template loaders in the compress management command.

  • Documented included filters.

  • Added Slim It filter.

  • Added new CallbackOutputFilter to ease the implementation of Python-based callback filters that only need to pass the content to a callable.

  • Make use of django-appconf for settings handling and versiontools for versions.

  • Uses the current context when rendering the render templates.

  • Added post_compress signal.


  • Fixed stdin handling of precompiler filter.


  • Fixed encoding related issue.

  • Minor cleanups.


  • Fixed the precompiler support to also use the full file path instead of a temporarily created file.

  • Enabled test coverage.

  • Refactored caching and other utility code.

  • Switched from SHA1 to MD5 for hash generation to lower the computational impact.


  • Replace naive with rJSmin ( and fixed a few problems with JavaScript comments.

  • Fixed converting relative URLs in CSS files when running in debug mode.


If you relied on the split_contents method of Compressor classes, please make sure a fourth item is returned in the iterable that denotes the base name of the file that is compressed.


  • Fixed import error when using the standalone django-staticfiles app.


  • Created new parser, HtmlParser, based on the stdlib HTMLParser module.

  • Added a new default AutoSelectParser, which picks the LxmlParser if lxml is available and falls back to HtmlParser.

  • Use unittest2 for testing goodness.

  • Fixed YUI JavaScript filter argument handling.

  • Updated bundled jsmin to use version by Dave St.Germain that was refactored for speed.


  • Fixed Closure filter argument handling.


  • Fixed options mangling in CompilerFilter initialization.

  • Fixed tox configuration.

  • Extended documentation and README.

  • In the compress command ignore hidden files when looking for templates.

  • Restructured utilities and added staticfiles compat layer.

  • Restructered parsers and added a html5lib based parser.


  • Minor bugfixes that caused the compression not working reliably in development mode (e.g. updated files didn’t trigger a new compression).


  • Fixed staticfiles support to also use its finder API to find files during development – when the static files haven’t been collected in STATIC_ROOT.

  • Fixed regression with the COMPRESS setting, pre-compilation and staticfiles.


Major improvements and a lot of bugfixes, some of which are:

  • New precompilation support, which allows compilation of files and hunks with easily configurable compilers before calling the actual output filters. See the COMPRESS_PRECOMPILERS for more details.

  • New staticfiles support. With the introduction of the staticfiles app to Django 1.3, compressor officially supports finding the files to compress using the app’s finder API. Have a look at the documentation about remote storages in case you want to use those together with compressor.

  • New compress management command which allows pre-running of what the compress template tag does.

  • Various performance improvements by better caching and mtime checking.

  • Deprecated COMPRESS_LESSC_BINARY setting because it’s now superseded by the COMPRESS_PRECOMPILERS setting. Just make sure to use the correct mimetype when linking to less files or adding inline code and add the following to your settings:

        ('text/less', 'lessc {infile} {outfile}'),
  • Added cssmin filter (compressor.filters.CSSMinFilter) based on Zachary Voase’s Python port of the YUI CSS compression algorithm.

  • Reimplemented the dog-piling prevention.

  • Make sure the CssAbsoluteFilter works for relative paths.

  • Added inline render mode. See usage docs.

  • Added mtime_cache management command to add and/or remove all mtimes from the cache.

  • Moved docs to Read The Docs:

  • Added optional storage backend that gzips of the saved files automatically for easier deployment.

  • Reimplemented a few filters on top of the new compressor.filters.base.CompilerFilter to be a bit more DRY.

  • Added tox based test configuration, testing on Django 1.1-1.3 and Python 2.5-2.7.