Skip to main content

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/core from esm.sh CDN (~1kb gzipped)
  • Calls ctx.observe(document.body)
  • Keeps window.__askableContext updated 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

askable_django-0.1.2.tar.gz (5.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

askable_django-0.1.2-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

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

Hashes for askable_django-0.1.2.tar.gz
Algorithm Hash digest
SHA256 9ca2f42c850310a4e50c777690b39019e02b760503a384ff7997fddb97493f68
MD5 2e671ba181a2b590e0b222779f976d0c
BLAKE2b-256 349add746f36691b6941b3d23bff529fcb65592fad775ac4f6487bc8caee5eb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for askable_django-0.1.2.tar.gz:

Publisher: publish-python.yml on askable-ui/askable

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for askable_django-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c40333e2754cb20e2fb32c139a23cb31d4bfb2fce91fc508dfbe4522c7bd81fe
MD5 07fe06b9de066b75b681f2288805445f
BLAKE2b-256 070122628548b8a03fb2d6874c9b67a888827b2bdb6e0d987ed17c37fcfafc1f

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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