Adding a Datasette ASGI app to Django

Datasette is implemented as an ASGI application.

Django can be run and deployed using ASGI.

At the DjangoCon Sprints this morning I figured out how to run Datasette inside a Django application, talking to the same SQLite databases as Django itself.

Installing Datasette

Run this in the same environment as your Django application (or add it to requirements.txt or similar):

pip install datasette

Adding it to asgi.py

Django projects have an asgi.py module automatically generated for them when the project is created.

Replace its content with the following (careful to replace my_django_application.settings with the correct value):

from datasette.app import Datasette
from django.core.asgi import get_asgi_application
from django.db import connections
import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_application.settings")


datasette_application = Datasette(
    [
        str(db["NAME"])
        for db in connections.databases.values()
        if db["ENGINE"] == "django.db.backends.sqlite3"
    ],
    settings={
        "base_url": "/datasette/",
    },
).app()
django_application = get_asgi_application()


async def application(scope, receive, send):
    if scope["type"] == "http" and scope.get("path").startswith("/datasette/"):
        await datasette_application(scope, receive, send)
    else:
        await django_application(scope, receive, send)

Prior to this change, the file contained application = get_asgi_application(). application is the ASGI application that will be served.

This code replaces that with a tiny ASGI app that looks at the incoming scope["path"] and, if it starts with /datasette/, sends it to the Datasette ASGI application. All other requests are sent to Django.

The Datasette() constructor at the start finds all SQLite databases that have been configured for Django, extracts their file path (db["NAME"] is a path object for SQLite databases) and passes that to the Datasette constructor.

It also sets base_url to /datasette/ so that Datasette will know how to generate correct URLs when it is mounted at that path, as opposed to the root / path of the server.

Running it with Uvicorn

Since this is an ASGI app, running ./manage.py runserver will no longer do the right thing.

Instead, you need to install and use an ASGI server to run Django.

I like Uvicorn for this.

Install it with pip install uvicorn, then start a local Django server running with:

uvicorn my_django_application.asgi:application

Add --reload to cause it to automatically reload any time a file on disk is changed:

uvicorn my_django_application.asgi:application --reload

Using Datasette

With this in place, browsing to http://127.0.0.1:8000/datasette/ will provide a Datasette interface for running read-only queries against your Django SQLite databases.

Created 2022-10-20T11:01:36-07:00, updated 2022-10-20T12:30:54-07:00 · History · Edit