django-turso
A Django database backend for Turso with native async execution.
Django still builds the queries and SQL. This backend replaces execution and row loading on the async path: a query suspends the calling asyncio task and the driver's completion descriptor wakes the same event loop. It starts no Python worker thread.
Status
Alpha. The backend needs the native async binding (turso.aio.native) from the withlogicco/turso fork of pyturso. pyturso on PyPI does not ship that module yet, so the backend fails to import with it. Install the fork after this package (see below).
Install
pip install django-turso
pip install --force-reinstall --no-deps \
"pyturso @ git+https://github.com/withlogicco/turso.git@22df675ff171ff567c8083dcf5308c3b12d106cb#subdirectory=bindings/python"
Building the fork needs a Rust toolchain; maturin builds the wheel.
Requirements:
- Linux.
- Python 3.14.
- Django 6.1.
- dj11, which owns the async ORM (
dj11.aorm).
Configure
from django_turso.compat import connect_native
DATABASES = {
"default": {
"ENGINE": "django_turso.db.backends.turso",
"NAME": BASE_DIR / "default.db",
"OPTIONS": {
"transaction_mode": "IMMEDIATE",
"async_connect": connect_native,
"strict_native_async": True,
},
},
}
strict_native_async rejects a driver that runs I/O on a Python worker thread. connect_pyturso opens pyturso's thread-based wrapper; use it only for compatibility tests.
Other OPTIONS:
pool.max_size: number of extra read-only connections. They open on the same event loop and never write.vfsandstorage: passed to the native driver.init_command:;-separated SQL run on each new connection.
Use
Give a model the async manager from dj11.aorm:
from django.db import models
from dj11.aorm.manager import AsyncManager
class Log(models.Model):
service = models.TextField()
observed_at = models.BigIntegerField()
objects = AsyncManager()
Then query it:
logs = Log.objects.filter(service="api")
async for log in logs.order_by("-observed_at"):
print(log.service)
log = await logs.aget(pk=log_id)
count = await logs.acount()
await logs.abulk_create(batch)
Run migrations before serving traffic:
./manage.py migrate
The async path does not support related loading, joins, deferred loading, select_for_update(), conflict updates, or aggregates that need a subquery. These raise dj11.aorm.exceptions.NotSupportedError before any database I/O.
What this package holds
- The backend,
django_turso.db.backends.turso. It subclasses Django's SQLite backend and reuses its SQL. ?placeholder conversion (django_turso.sql).- A bounded compiled-statement cache keyed by SQL text (
django_turso.stmt_cache). - INSERT SQL-text reuse that skips Django's compiler for repeated insert shapes (
django_turso.inserts). - Driver factories and capability checks (
django_turso.compat). - Async connection cleanup (
django_turso.lifecycle). django_turso.driver.TursoConnection, which addscompact()to thedj11.aormconnection protocol.
The database-independent async ORM (AsyncQuerySet, AsyncManager, the driver protocol) lives in dj11.aorm. This package re-exports none of it.
Threads
Database I/O runs on the event loop's thread. To count threads, run a single Uvicorn worker without the autoreloader and read /proc in the process that owns the connections. Record native database threads apart from Python threads if a later engine revision adds any.
Metadata
Release files for django-turso 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| django_turso-0.1.0.tar.gz | 15.4 kB | Without provenance | Details for django_turso-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_turso-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for django_turso-0.1.0-py3-none-any.whl |
Total release size: 36.3 kB
Release files / django_turso-0.1.0.tar.gz
| Download URL | django_turso-0.1.0.tar.gz |
|---|---|
| Size | 15.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b188695696d1bab2c4fda2c8b119df49ea9d173a78ff2cade07416d48b8cb3d9
|
|
BLAKE2b-256 checksum How to use checksums |
ebdea8231a51fbbf1af3e3dcdc70ea80d4f81bc45db74dbae8ca9da22be8155a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / django_turso-0.1.0-py3-none-any.whl
| Download URL | django_turso-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d5a4ccfc90ddbc1f8d7c4e9dad21759cdf1332d1d9b8cf603825b331add815a9
|
|
BLAKE2b-256 checksum How to use checksums |
a3a1e2e947a65040d6569c3327ee44a789d4b6675c5b7cfc6c51c042e3409839
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for django-turso 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.