ClickHouse Django
Use ClickHouse from Django without raw SQL in every view
The Django ORM is built for your transactional database. For analytics in ClickHouse, hypequery gives your views and tasks named measures and dimensions, scoped to the signed-in customer, from definitions you write once in Python.
Works in
Sync and async views
Tenant from
request.user
Setup
One app, one middleware
The ORM doesn’t fit ClickHouse
Django’s ORM expects transactions, migrations, and row updates. Analytics on ClickHouse is aggregations over billions of rows, so teams fall back to raw SQL strings.
Raw SQL spreads through views
Each view and Celery task writes its own revenue query. They drift, and none of them is reviewed as a definition.
Tenant scoping is manual
Every query has to remember the organisation filter. The one that forgets shows one customer another customer’s numbers.
Views and tasks
Query named measures from any view
Add the app and middleware, point HYPEQUERY at your datasets, and every view gets request.analytics: a client already scoped to the signed-in user’s organisation. The query is planned from your dataset, with the tenant filter added for you.
- Sync views get the sync client; async views get the async one, from the same attribute
manage.py checkvalidates the setting without connecting to ClickHouse- A query without a tenant fails instead of reading every customer
- Celery tasks use
get_client()and bind the tenant explicitly
views.py
A tenant-scoped Django view
The client is built on first use, closed at exit, and rebuilt in each forked worker. Results are plain dicts, ready for JsonResponse or a template.
Tasks and commands
The same numbers in Celery, commands and exports
Outside a request, get_client() returns the process-wide client and you bind the tenant explicitly. Reports, exports and scheduled jobs use the same definitions as your views, and to_pandas() turns results into typed DataFrames.
The client connects on its first query, is closed when the process exits, and is rebuilt in each forked worker, so gunicorn and Celery prefork pools are safe.
For typed React hooks or the MCP bridge, mount hypequery’s HTTP endpoints in your URLconf with urls(api): no second service, and the session API uses your Django login.
tasks.py
A tenant-scoped Celery task
Results convert to a typed DataFrame for exports.
Where teams usually get stuck
Questions teams ask
Django ClickHouse backend
You don’t need ClickHouse as a Django database. Keep the ORM on Postgres and query ClickHouse through datasets.
Django analytics dashboard
Views return measures by dimension and time grain, scoped to the user’s organisation.
Celery jobs on ClickHouse
Reports and exports use the same definitions as the app, with an explicit tenant for each run.
Is there a Django integration?
Yes: hypequery.contrib.django adds settings, a system check, request.analytics middleware, and clients for tasks and commands.
Further reading
Go deeper where it actually helps
Next step
Replace one raw SQL view
Define the dataset behind one Django report, then swap its SQL for a scoped dataset query.
Open source, and it runs in your own backend. Want it hosted?