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, defer, type="module", nomodule, integrity, or cross-origin URLs are 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.
  • Currently only checked on Python 3.14 and Django 6.0

TODO

  • improve template ergonomics
  • tests
  • dependency 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.1.tar.gz (1.1 MB 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.1-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_suppressor-0.1.1.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • 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.1.tar.gz
Algorithm Hash digest
SHA256 06fd4ae45baa290485a1fb0e8116bf49527de2e7a6a380a4ce34dfe702f5311b
MD5 9da5ed7777f3e13ff4c9685063d1a789
BLAKE2b-256 0e921c7871a9fa65ec3c2cc7f934a41e36e64e487c40f5adf2e92de04d4021f8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_suppressor-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3f5226f0b687550871a2fb965f66aad97841dc912235d906319a92075fd3868b
MD5 da38dd6ffc8da61571d9485a89c2d9b8
BLAKE2b-256 ebb1af7504a4d2412ba24e9d0622539d0bff30c89513ce8b4fd5a63ab691ffdc

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