SPA framework for Django — one script tag turns Django templates into a full SPA
Project description
django-hilo
SPA framework for Django. One <script> tag turns Django templates into a full SPA.
Works with Hilo.js — the client-side library that handles navigation, DOM morphing, signals, and real-time communication.
Installation
pip install django-hilo
# settings.py
INSTALLED_APPS = [
...
'hilo',
]
MIDDLEWARE = [
...
'hilo.middleware.HiloMiddleware',
]
Quick Start
1. Base template
{% load hilo %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My App{% endblock %}</title>
</head>
<body>
<nav data-permanent>
<a href="/">Home</a>
<a href="/products/">Products</a>
</nav>
{% hilo_content %}
{% block content %}{% endblock %}
{% endhilo_content %}
{% hilo_scripts %}
</body>
</html>
2. Views with @fragment
from hilo.decorators import fragment
@fragment('products/list.html')
def product_list(request):
return {'products': Product.objects.all()}
That's it. Links are intercepted automatically. No hx-get, no hx-target, no attributes needed.
Features
Middleware
HiloMiddleware handles:
- Redirect conversion — Django redirects become
X-Hilo-Redirectheaders (no full page reload) - Asset versioning —
X-Hilo-Versionheader for cache busting - Request detection —
request.is_hiloboolean available in views
@fragment decorator
Renders the appropriate template based on request type:
- Hilo request → renders only the partial template (fragment)
- Normal request → renders the full page (with base layout)
@fragment('products/list.html', 'products/page.html')
def product_list(request):
return {'products': Product.objects.all()}
Response helpers
from hilo.response import hilo_redirect, hilo_trigger, hilo_title, hilo_url
# Redirect via Hilo (no full reload)
return hilo_redirect('/products/')
# Trigger client-side events
response = render(request, 'template.html', context)
return hilo_trigger(response, {'showMessage': {'message': 'Saved!', 'type': 'success'}})
# Set page title
return hilo_title(response, 'Products')
Streaming actions (like Turbo Streams)
from hilo.response import HiloStreamResponse
def add_message(request):
response = HiloStreamResponse()
response.append('#messages', '<div class="message">New message!</div>')
response.update('#counter', '<span>42</span>')
response.remove('#typing-indicator')
return response
Template tags
{% load hilo %}
{% hilo_scripts %} {# Inject hilo.min.js + config #}
{% hilo_content %}...{% endhilo_content %} {# Main content area #}
{% hilo_permanent %}...{% endhilo_permanent %} {# Never morphed #}
{# Streaming actions in templates #}
{% hilo_stream "append" "#messages" %}
<div class="message">{{ message.text }}</div>
{% endhilo_stream %}
Configuration
# settings.py
HILO = {
'VERSION': 'auto', # Asset version ('auto', fixed string, or '')
'JS_PATH': 'js/hilo.min.js', # Path to hilo.min.js in STATIC_URL
'PREFIX': 'h', # Behavior prefix (data-h="toggle")
'DEBUG': False, # Enable debug logging
'NAV': True, # Enable SPA navigation (True, False, or dict)
}
License
MIT
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_hilo-0.1.0.tar.gz.
File metadata
- Download URL: django_hilo-0.1.0.tar.gz
- Upload date:
- Size: 10.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51255e54706751d4485eeba1032efb09a306177d013aeae87fb0963b7890d067
|
|
| MD5 |
0ba309f97ab589fd377613d82f768fa6
|
|
| BLAKE2b-256 |
38d4f457fa28314a2ff175a36f77581f863ec6bfaa921d3ecc0e2afac7a296b3
|
Provenance
The following attestation bundles were made for django_hilo-0.1.0.tar.gz:
Publisher:
publish.yml on ERPlora/django-hilo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_hilo-0.1.0.tar.gz -
Subject digest:
51255e54706751d4485eeba1032efb09a306177d013aeae87fb0963b7890d067 - Sigstore transparency entry: 1200490627
- Sigstore integration time:
-
Permalink:
ERPlora/django-hilo@b57e7f2510728f80306a5b752a4b1cb26922b813 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ERPlora
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b57e7f2510728f80306a5b752a4b1cb26922b813 -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_hilo-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_hilo-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c6e86e4b5b0b1045b2dc01fa7381138ebd907ad2a413b344d4b5fde5a5c1028
|
|
| MD5 |
77b57fa64d0060b6136f48a86d3284b7
|
|
| BLAKE2b-256 |
7420dd372b920b01ff29c5c7a7ab65e4a25bf484ad00dc90d53ba6f83bd57b4a
|
Provenance
The following attestation bundles were made for django_hilo-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ERPlora/django-hilo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_hilo-0.1.0-py3-none-any.whl -
Subject digest:
9c6e86e4b5b0b1045b2dc01fa7381138ebd907ad2a413b344d4b5fde5a5c1028 - Sigstore transparency entry: 1200490788
- Sigstore integration time:
-
Permalink:
ERPlora/django-hilo@b57e7f2510728f80306a5b752a4b1cb26922b813 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ERPlora
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b57e7f2510728f80306a5b752a4b1cb26922b813 -
Trigger Event:
release
-
Statement type: