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
- Add
suppressorto your installed apps and middleware:
INSTALLED_APPS = [
"django.contrib.staticfiles",
"suppressor",
...
]
MIDDLEWARE = [
...
"suppressor.middleware.SuppressorMiddleware", # near the end
]
- Include the suppressor URLs in your root URL config:
from django.urls import include, path
urlpatterns = [
path("", include("suppressor.urls")),
...
]
- 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.
- Run
collectstaticbefore 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"(withouturl()) is not rewritten StreamingHttpResponseis 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06fd4ae45baa290485a1fb0e8116bf49527de2e7a6a380a4ce34dfe702f5311b
|
|
| MD5 |
9da5ed7777f3e13ff4c9685063d1a789
|
|
| BLAKE2b-256 |
0e921c7871a9fa65ec3c2cc7f934a41e36e64e487c40f5adf2e92de04d4021f8
|
File details
Details for the file django_suppressor-0.1.1-py3-none-any.whl.
File metadata
- Download URL: django_suppressor-0.1.1-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f5226f0b687550871a2fb965f66aad97841dc912235d906319a92075fd3868b
|
|
| MD5 |
da38dd6ffc8da61571d9485a89c2d9b8
|
|
| BLAKE2b-256 |
ebb1af7504a4d2412ba24e9d0622539d0bff30c89513ce8b4fd5a63ab691ffdc
|