Safe natural-language querying over explicitly registered Django models.
Project description
Django AskLens
Django AskLens is a reusable Django + DRF package for safe natural-language querying over explicitly registered Django models.
AskLens does not let an LLM write SQL. It asks a provider for structured JSON, validates the plan against your registered catalog and permissions, compiles a read-only Django ORM query, executes with limits, and returns table/chart-ready JSON.
Status: alpha. APIs may change before a stable release.
What it provides
- Explicit semantic resource registration.
- Permission-scoped catalog and capabilities endpoints.
- Strict Pydantic
QueryPlanvalidation. - ORM-only list and aggregate query execution.
- Dummy provider for deterministic tests and demos.
- OpenAI-compatible live provider adapter.
- Query-run audit records.
- Frontend-agnostic
columns+dataJSON output. - Optional packaged browser UI for demos/reference use.
Quickstart
Install:
python -m pip install django-asklens
Add the app and DRF:
INSTALLED_APPS = [
# ...
"rest_framework",
"django_asklens",
]
Mount the API:
from django.urls import include, path
urlpatterns = [
path("", include("django_asklens.api.urls")),
]
Run migrations for AskLens audit records:
python -m django migrate asklens
Register a resource during app startup:
from django_asklens import Metric, register
from shop.models import Order
def visible_orders(request):
if not getattr(request.user, "is_authenticated", False):
return Order.objects.none()
return Order.objects.filter(account__memberships__user=request.user)
register(
model=Order,
name="orders",
label="Orders",
description="Orders visible to the current user.",
default_date_field="created_at",
fields={
"id": {"label": "Order ID"},
"status": {"label": "Status"},
"created_at": {"label": "Created date"},
"customer.email": {
"label": "Customer email",
"sensitive": True,
"requires_permission": "customers.view_pii",
},
"total_cents": {"label": "Total in cents"},
},
metrics=[
Metric("order_count", op="count", field="id", label="Orders"),
Metric("revenue", op="sum", field="total_cents", label="Revenue"),
],
requires_permission="orders.view_reports",
base_queryset=visible_orders,
)
requires_permission on the resource gates catalog visibility and query validation for the whole resource. Field-level requires_permission gates individual fields such as PII.
Start with the deterministic dummy provider:
DJANGO_ASKLENS = {
"LLM_BACKEND": "dummy",
"DUMMY_PLANS": {
"Show orders by status": {
"resource": "orders",
"intent": "aggregate",
"group_by": [{"field": "status"}],
"metrics": [{"name": "order_count", "op": "count", "field": "id"}],
"limit": 100,
"visualization": {"type": "bar", "x": "status", "y": "order_count"},
}
},
}
Ask through the API:
POST /asklens/query/
Content-Type: application/json
{"question": "Show orders by status"}
Successful data responses include:
{
"run_id": 1,
"question": "Show orders by status",
"response_type": "query",
"plan": {"resource": "orders", "intent": "aggregate", "limit": 100},
"columns": [{"key": "status", "label": "Status", "type": "string"}],
"data": [{"status": "paid", "order_count": 12}],
"row_count": 1,
"result_metadata": {
"limit": 100,
"limit_scope": "groups",
"limit_reached": false
},
"visualization": {"type": "bar"}
}
Help questions such as show me example queries return response_type: "capabilities" with suggestions instead of running a database query.
Building a UI
AskLens is API-first. Build your own UI with React, Vue, HTMX, Django templates, a mobile client, or any chart/table library by rendering the returned columns and data arrays.
The packaged frontend is optional and intended as a dependency-free demo/reference UI. Projects that need product-specific layout, charts, saved queries, or workflows should call the API directly. See Building a custom AskLens UI.
Optional packaged frontend
If you want the built-in reference UI:
urlpatterns = [
path("", include("django_asklens.api.urls")),
path("", include("django_asklens.frontend.urls")), # /asklens/ui/
]
Gate the page for selected users with:
DJANGO_ASKLENS = {
"FRONTEND_PERMISSION_CHECK": "myapp.permissions.can_use_asklens_frontend",
}
API route permissions still apply to every API call. The frontend permission check only controls whether the packaged page can load.
Live providers
The default backend is dummy and makes no network calls. To use an OpenAI-compatible provider:
import os
DJANGO_ASKLENS = {
"LLM_BACKEND": "openai_compatible",
"LLM_BASE_URL": "https://api.openai.com/v1",
"LLM_API_KEY": os.environ["OPENAI_API_KEY"],
"LLM_MODEL": "gpt-4.1-mini",
"LLM_TEMPERATURE": 0,
}
Gemini can be used through its OpenAI-compatible endpoint:
DJANGO_ASKLENS = {
"LLM_BACKEND": "openai_compatible",
"LLM_BASE_URL": "https://generativelanguage.googleapis.com/v1beta/openai",
"LLM_API_KEY": os.environ["GEMINI_API_KEY"],
"LLM_MODEL": "gemini-2.5-flash",
"LLM_TEMPERATURE": 0,
}
Live provider tests are opt-in and skipped by default. See Provider configuration.
Safety posture
- Only explicitly registered resources and fields are queryable.
- Every query starts from the resource
base_queryset(request)hook. - Sensitive fields are hidden unless explicitly permissioned.
- Provider output is untrusted and always validated before execution.
- AskLens executes read-only Django ORM queries only.
- AskLens does not execute LLM-generated SQL.
- AskLens does not create, update, or delete application data.
- AskLens does not send database rows, sample values, secrets, credentials, or
.envcontent to providers by default. - Query runs are audited.
Review the security checklist and production checklist before enabling AskLens outside local development.
Alpha scope and safety boundaries
- APIs may change before a stable release.
- AskLens supports read-only list and aggregate questions over explicitly registered resources.
- Query quality depends on clear resource, field, description, and metric registration.
- Live provider behavior varies by model and prompt complexity;
DummyProviderremains the deterministic default for tests and demos. - SQL generation/execution is intentionally out of scope. AskLens uses validated QueryPlan JSON and Django ORM compilation only.
- Writes and mutations are intentionally out of scope.
- Server-side saved queries, dashboard builders, and a dedicated help endpoint are not part of the alpha package surface.
- The packaged frontend is a reference/demo UI; custom product UIs should call the API directly.
- Read-only replica/database routing is a host-project deployment concern in alpha.
- Current package metadata and CI target Django 6.x.
Documentation
- Installation
- Usage guide
- Custom UI guide
- Registration API
- Provider configuration
- Contributing
- Security policy
- Security checklist
- Production checklist
- Multi-tenant security
- Evaluation fixtures
- Runnable complex test project
- Changelog
Development
Use Python 3.12 or newer and uv for local development.
uv sync --group dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
The package remains standards-based and setuptools-backed; uv is used for contributor workflows, not as a runtime dependency.
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_asklens-0.1.0a0.tar.gz.
File metadata
- Download URL: django_asklens-0.1.0a0.tar.gz
- Upload date:
- Size: 97.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8534fdbb06ed6b684e49090e551db7e4c2ba0a2ab01083187d5737fa4c6be0f
|
|
| MD5 |
ba52b0db4f575bd6f3f249c44407173b
|
|
| BLAKE2b-256 |
e0dfd59ee92b4fbb829d10adb5199565c686e6e956732f11da1f450a3884a9ae
|
File details
Details for the file django_asklens-0.1.0a0-py3-none-any.whl.
File metadata
- Download URL: django_asklens-0.1.0a0-py3-none-any.whl
- Upload date:
- Size: 89.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23cdd78170603f49a701f3210ee4e8743158225bc3b536a5549ae9881c05dfa3
|
|
| MD5 |
5987048b8164dcce55bb62d056d8344a
|
|
| BLAKE2b-256 |
51ddf0623490dfd3adcc448ad5500642919c4d23d94c209e0f497e05c541023e
|