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)
  • Bundles plain external <script src> / <link rel="stylesheet"> and plain inline <script> / <style>
  • Any tag carrying extra attributes (async, defer, type="module", nomodule, integrity, media/title/disabled, nonce, crossorigin, referrerpolicy, id, data-*, …) or a cross-origin / non-http(s) URL is preserved unchanged
  • CSS relative url(...) references are rewritten to absolute paths; bare @import "file.css" (without url()) is not rewritten
  • StreamingHttpResponse is not processed
  • See also "TODO" section below.

Tested against

CI runs the test suite across Python 3.10–3.14 and Django 4.2, 5.0, 5.1, 5.2 and 6.0 (only supported combinations of each).

TODO

  • improve template ergonomics
  • preserved (ignored) tags can reorder CSS cascade / JS execution vs the bundle

Status

Under development. See SPEC-0-1-0.md for the original design specification and rationale — it is the historical founding spec the project evolves from, not a description of current behavior.

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.2.0.tar.gz (36.1 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.2.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_suppressor-0.2.0.tar.gz
  • Upload date:
  • Size: 36.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for django_suppressor-0.2.0.tar.gz
Algorithm Hash digest
SHA256 6e6c6ee2730ecc412512f580d973b0151523e95ffa58be5072070bfdb76800b3
MD5 e03608d6148d4c55d3758baedef8c7b0
BLAKE2b-256 8cb8a994599803fac1024074069185ee28b9c93718d29b9efd4172dbf5d59efb

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_suppressor-0.2.0.tar.gz:

Publisher: publish.yml on frnhr/django-suppressor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

File hashes

Hashes for django_suppressor-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e9ffb948aedd084860c4e755c79db5f7e188c439ed5d9802e2938bf8899257b5
MD5 8abd6c5858f3dfba799a8c2856ea2017
BLAKE2b-256 c38e7258459078822fc9895e3b2f04c62dfe31626885945d9182f8d9ef3782f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_suppressor-0.2.0-py3-none-any.whl:

Publisher: publish.yml on frnhr/django-suppressor

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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