django-xinclude
Project description
Render a template using htmx with the current context.
Requirements
Python 3.10 to 3.12 supported.
Django 4.2 to 5.0 supported.
Setup
Install from pip:
python -m pip install django-xinclude
Add it to your installed apps:
INSTALLED_APPS = [
...,
"django_xinclude",
...,
]
Include the app URLs in your root URLconf:
from django.urls import include, path
urlpatterns = [
...,
path("__xinclude__/", include("django_xinclude.urls")),
]
You can use a different prefix if required.
Usage
Once installed, load the xinclude library and use the tag passing the template that you want to include:
{% load xinclude %}
{% xinclude "footer.html" %}{% endxinclude %}
Every feature of the regular include tag is supported, including the use of with and only.
You can use the following htmx-specific arguments:
hx-trigger: corresponds to the hx-trigger htmx attribute. Defaults to load once.
swap-time: corresponds to the swap timing of the hx-swap htmx attribute.
settle-time: corresponds to the settle timing of the hx-swap htmx attribute.
“Primary nodes” may be passed along to render initial content prior to htmx swapping. For example:
{% xinclude "footer.html" %}
<div>Loading...</div>
{% endxinclude %}
django-xinclude plays well with the excellent django-template-partials package, to select specific partials on the target template.
Advanced usage
Below is a more complete example making use of the htmx transition classes. Note the intersect once trigger, which will fire the request once when the element intersects the viewport.
<style>
.htmx-swapping > #loading {
opacity: 0;
transition: opacity 1s ease-out;
}
</style>
{% xinclude "magic.html" with wand="🪄" hx-trigger="intersect once" swap-time="1s" settle-time="1s" %}
<div id="loading">
Loading...
</div>
{% endxinclude %}
magic.html:
<style>
#items.htmx-added {
opacity: 1;
animation: appear ease-in 500ms;
}
</style>
<div id="items">
🔮 {{ wand }}
</div>
You can preload the xinclude libary in every template by appending to your TEMPLATES builtins setting. This way you don’t need to repeat the {% load xinclude %} in every template that you need the tag:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
...,
"OPTIONS": {
"builtins": [
"django_xinclude.templatetags.xinclude",
],
},
},
]
How It Works
django-xinclude first checks if it needs to render the target template synchronously; see the Section below for cases where this might be useful. If this is not the case, it stores the current context and the target template to the cache and constructs a url with a fragment_id that targets an internal view. It then renders a parent div element containing all the necessary htmx attributes. Once the htmx request fires, the view fetches the cache context and template that match the passed fragment_id and uses that context to render the template.
Cache
django-xinclude uses either the cache that corresponds to the XINCLUDE_CACHE_ALIAS setting, if specified, or CACHES["default"]. When setting a new cache key, it finds unpickable values and discards them. If you want to see which keys get discarded, update your settings.LOGGERS to include "django_xinclude" with "level": "DEBUG".
Rendering synchronously
There are cases where you might want to conditionally render fragments synchronously (i.e. use the regular include). For example, you could render synchronously for SEO purposes, when robots are crawling your pages, but still make use of the htmx functionality for regular users. django-xinclude supports this, it checks for a xinclude_sync attribute on the request and renders synchronously if that evaluates to True. So you can add a custom middleware that sets the xinclude_sync attribute upon your individual conditions.
See also Configuration below for the XINCLUDE_SYNC_REQUEST_ATTR setting.
Configuration
XINCLUDE_CACHE_ALIAS: str
The cache alias that django-xinclude will use, it defaults to CACHES["default"].
XINCLUDE_CACHE_TIMEOUT: int
The number of seconds that contexts will remain in cache. If the setting is not present, Django will use the default timeout argument of the appropriate backend in the CACHES setting.
XINCLUDE_SYNC_REQUEST_ATTR: str
The request attribute that django-xinclude will check on to determine if it needs to render synchronously. It defaults to xinclude_sync.
Running the tests
Fork, then clone the repo:
git clone git@github.com:your-username/django-xinclude.git
Set up a venv:
python -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[tests,dev]'
Set up the pre-commit hooks:
pre-commit install
Then you can run the tests with the just command runner:
just test
Or with coverage:
just coverage
If you don’t have just installed, you can look in the justfile for the commands that are run.
Complementary packages
django-htmx: Extensions for using Django with htmx.
django-template-partials: Reusable named inline partials for the Django Template Language.
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
Hashes for django_xinclude-0.1.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | aa8a6960266c2ec95220879a83bcd34a4f789e96000484dc5511aee13cefe003 |
|
MD5 | 07479bb10cad12fdacac1eb5d37c6832 |
|
BLAKE2b-256 | 72570e24837b868219e98045dff8095076cc6edb5ecdbda6c98eb1bbc61e1c98 |