Skip to main content

HTML asset capture and runtime bundling for Django

Project description

django-suppressor

HTML asset capture and runtime bundling for Django.

Suppresses individual <link> and <script> tags in your templates and replaces them with bundled equivalents at runtime.

Installation

pip install django-suppressor

Rationale

Django templates scatter <link> and <script> tags across base templates, child templates, and includes. Each tag means a separate HTTP request. Existing bundling tools either require you to rewrite all asset references as custom tags or operate as offline build steps disconnected from the template system.

Suppressor takes a different approach: wrap a template region, let Django render it normally, then parse the resulting HTML fragment to find asset tags. Captured tags are removed from the fragment and their contents are concatenated into a single content-addressed bundle served at runtime. Child templates keep writing plain HTML — no special asset registration required.

This is deliberately scoped to explicit template regions rather than full-page rewriting: safer, faster, predictable ordering, and easy to debug.

Quick Start

  1. Add suppressor to your installed apps and middleware:
INSTALLED_APPS = [
    "django.contrib.staticfiles",
    "suppressor",
    ...
]

MIDDLEWARE = [
    ...
    "suppressor.middleware.SuppressorMiddleware",  # near the end
]
  1. Include the suppressor URLs in your root URL config:
from django.urls import include, path

urlpatterns = [
    path("", include("suppressor.urls")),
    ...
]
  1. Wrap asset regions in your base template:
{% load suppressor_capture %}

<head>
    {% suppressor_emit_css "head" %}

    {% suppressor_capture "head" only_css %}
        <link rel="stylesheet" href="{% static 'css/base.css' %}">
        <link rel="stylesheet" href="{% static 'css/theme.css' %}">
        {% block extra_css %}{% endblock %}
    {% endsuppressor_capture %}
</head>

<body>
    ...

    {% suppressor_capture "body_js" only_js %}
        <script src="{% static 'js/vendor.js' %}"></script>
        <script src="{% static 'js/app.js' %}"></script>
        {% block extra_js %}{% endblock %}
    {% endsuppressor_capture %}

    {% suppressor_emit_js "body_js" %}
</body>

Child templates keep using plain <link> and <script> tags inside the inherited blocks. Suppressor captures them, bundles by type, and emits a single content-addressed URL per region.

  1. Run collectstatic before use — suppressor reads from staticfiles storage, not finders:
python manage.py collectstatic

Configuration

Bundling is controlled by SUPPRESSOR_ENABLED, which defaults to not DEBUG. Override it to test bundling locally:

SUPPRESSOR_ENABLED = True

Bundle content is stored using Django's cache framework under the suppressor alias. A FileBasedCache default is auto-configured if you don't define one. To use a different backend:

CACHES = {
    ...
    "suppressor": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": "127.0.0.1:11211",
    },
}

Limitations

  • Only processes explicitly wrapped template regions (no full-page rewriting)
  • Supports classic external <script src> and <link rel="stylesheet"> tags only
  • Tags with async, type="module", nomodule, integrity, or cross-origin URLs are preserved unchanged
  • CSS relative url(...) references may break when bundled (rewriting planned for v0.1.1)
  • StreamingHttpResponse is not processed
  • See also "TODO" section below.
  • Currently only checked on Python 3.14 and Django 6.0

TOOD

  • Fix CSS url(...) relative paths
  • improve template ergomonice
  • tests
  • denedency matrix

Status

Under development. See SPEC-0-1-0.md for the design specification and a roadmap.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_suppressor-0.1.0.tar.gz (407.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_suppressor-0.1.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file django_suppressor-0.1.0.tar.gz.

File metadata

  • Download URL: django_suppressor-0.1.0.tar.gz
  • Upload date:
  • Size: 407.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for django_suppressor-0.1.0.tar.gz
Algorithm Hash digest
SHA256 da28a8d47b34290c834d1a269104b106b0092b15444ed631f5ef4f5096b0ebd7
MD5 680e592a0e5fc67b04d0dc3fb457ce40
BLAKE2b-256 242b846eaa5bb2c50d215aa7a11607e7be452e0c289085652f31a5a33b4fd0a9

See more details on using hashes here.

File details

Details for the file django_suppressor-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_suppressor-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 971ac7f1a9152e47c0966badf38f70ede1572fdd1a032977d7d0063afd921146
MD5 7e6c9819589e50d91f384397a4ec6a7b
BLAKE2b-256 17312dc11a813c3a3c8451c6231d3a2dace409a4069d6dabe2c804c645ec5dce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page