LLM-aware UI context for Django — template tags + auto-inject middleware
Project description
askable-django
Django binding for askable — template tags + auto-inject middleware for LLM-aware Django apps.
Install
pip install askable-django
Add to INSTALLED_APPS and optionally MIDDLEWARE:
INSTALLED_APPS = [
...
"askable",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"askable.middleware.AskableMiddleware", # auto-injects askable/core before </body>
...
]
Template tags
{% load askable_tags %}
{# Wrap any block — renders a <div data-askable="..."> around your content #}
{% askable meta=chart_meta %}
<canvas id="revenue-chart"></canvas>
{% endaskable %}
{# Custom tag name #}
{% askable meta=chart_meta as="section" %}
{{ chart|safe }}
{% endaskable %}
{# Inline — just the attribute, for when you control the element #}
<div {% askable_attr meta=chart_meta %} class="panel">
{{ content }}
</div>
{# Manual script tag (if you're NOT using AskableMiddleware) #}
{% askable_script %}
meta argument
Pass a Python dict or string. Dicts are JSON-serialized automatically:
# views.py
def dashboard(request):
return render(request, "dashboard.html", {
"chart_meta": {
"metric": "revenue",
"period": "Q3",
"value": "$2.3M",
}
})
{% askable meta=chart_meta %}
<canvas id="chart"></canvas>
{% endaskable %}
{# renders: <div data-askable='{"metric":"revenue","period":"Q3","value":"$2.3M"}'> #}
Middleware
AskableMiddleware automatically injects @askable/core before </body> on every HTML response. No template changes needed — just add it to MIDDLEWARE.
The injected script:
- Loads
@askable/corefromesm.shCDN (~1kb gzipped) - Calls
ctx.observe(document.body) - Keeps
window.__askableContextupdated with the current prompt string
Your own JavaScript can read the context as:
const context = window.__askableContext;
// → "User is focused on: — metric: revenue, period: Q3 — value "Q3 Revenue""
// or "No UI element is currently focused."
Wire it into your AI chat handler:
async function askAI(question) {
return fetch('/ai/chat/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
question,
context: window.__askableContext,
}),
});
}
# views.py
import json
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def ai_chat(request):
data = json.loads(request.body)
question = data['question']
ui_context = data.get('context', 'No UI element is currently focused.')
response = your_llm_client.chat(
system=f"You are a helpful assistant.\n\nCurrent UI context:\n{ui_context}",
user=question,
)
return JsonResponse({'answer': response})
Flask / FastAPI
No dedicated package needed — it's the same pattern without the middleware:
{# Jinja2 template #}
<div data-askable='{{ chart_meta | tojson }}'>
{{ chart_content }}
</div>
{# Before </body> #}
<script type="module">
import { createAskableContext } from 'https://esm.sh/@askable/core@0.1.0';
const ctx = createAskableContext();
ctx.observe(document.body);
ctx.on('focus', () => { window.__askableContext = ctx.toPromptContext(); });
</script>
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 askable_django-0.1.2.tar.gz.
File metadata
- Download URL: askable_django-0.1.2.tar.gz
- Upload date:
- Size: 5.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ca2f42c850310a4e50c777690b39019e02b760503a384ff7997fddb97493f68
|
|
| MD5 |
2e671ba181a2b590e0b222779f976d0c
|
|
| BLAKE2b-256 |
349add746f36691b6941b3d23bff529fcb65592fad775ac4f6487bc8caee5eb2
|
Provenance
The following attestation bundles were made for askable_django-0.1.2.tar.gz:
Publisher:
publish-python.yml on askable-ui/askable
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
askable_django-0.1.2.tar.gz -
Subject digest:
9ca2f42c850310a4e50c777690b39019e02b760503a384ff7997fddb97493f68 - Sigstore transparency entry: 1195494368
- Sigstore integration time:
-
Permalink:
askable-ui/askable@9212d62382e5505fa93ffaec667033ab8c232d7e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/askable-ui
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@9212d62382e5505fa93ffaec667033ab8c232d7e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file askable_django-0.1.2-py3-none-any.whl.
File metadata
- Download URL: askable_django-0.1.2-py3-none-any.whl
- Upload date:
- Size: 6.6 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 |
c40333e2754cb20e2fb32c139a23cb31d4bfb2fce91fc508dfbe4522c7bd81fe
|
|
| MD5 |
07fe06b9de066b75b681f2288805445f
|
|
| BLAKE2b-256 |
070122628548b8a03fb2d6874c9b67a888827b2bdb6e0d987ed17c37fcfafc1f
|
Provenance
The following attestation bundles were made for askable_django-0.1.2-py3-none-any.whl:
Publisher:
publish-python.yml on askable-ui/askable
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
askable_django-0.1.2-py3-none-any.whl -
Subject digest:
c40333e2754cb20e2fb32c139a23cb31d4bfb2fce91fc508dfbe4522c7bd81fe - Sigstore transparency entry: 1195494372
- Sigstore integration time:
-
Permalink:
askable-ui/askable@9212d62382e5505fa93ffaec667033ab8c232d7e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/askable-ui
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@9212d62382e5505fa93ffaec667033ab8c232d7e -
Trigger Event:
workflow_dispatch
-
Statement type: