# Migrating from Django

The concept map for a Django app. The runbook — phases, exit conditions, stop conditions — is
[Migrating an existing app](/migrating-an-existing-app); this page says what each Django term
becomes. `As of 2026-11`, against Django 6 ([docs.djangoproject.com](https://docs.djangoproject.com/)).

## Concept map

| Django | Ultimate |
|---|---|
| `urls.py` + a view that renders a template | a route file: [Routes and render modes](/routes-and-render-modes) |
| a view that writes, a DRF viewset | an `action`: [Actions](/actions) |
| a model | an `entity()`: [Entities and migrations](/entities-and-migrations) |
| a queryset, a manager method | a `query`: [Queries and live queries](/queries-and-live-queries) |
| `makemigrations`, `migrate` | `x db gen "<name>"`, then `x db migrate` |
| `startapp` | `x g resource <name>` ([CLI reference](/cli-reference)) |
| Celery tasks | a `job`: [Jobs and workflows](/jobs-and-workflows) |
| Celery beat | a `task`: [Scheduled tasks](/scheduled-tasks) |
| `django.contrib.auth` | [Auth](/auth) |
| permissions, `django-guardian` | a `policy`: [Policies and authz](/policies-and-authz) |
| Channels | a live query: [Realtime](/realtime) |
| `send_mail` | [Mail](/mail) |
| `FileField`, `django-storages` | [Storage and uploads](/storage-and-uploads) |
| `django.contrib.admin` | [Admin dashboard](/admin-dashboard) |
| `gettext` `.po` files | one flat catalog per locale: [I18n](/i18n) |
| DRF's schema, drf-spectacular | `openapi.json`, projected from every action: [Actions](/actions) |
| `pytest-django`, `TestCase` | [Testing](/testing) |
| `runserver` | `x dev` |

## What does not map

| Django | Why |
|---|---|
| Python and its packages | Bun only. A Python dependency is rewritten or bought as a service |
| MySQL, SQLite, Oracle | Postgres only, by design: [Home](/docs) |
| templates | pages render with SolidJS; interactive parts are islands. No converter |
| signals (`post_save`) | no implicit hooks: the write is an `action` or a `mutator` that says what it does ([Actions](/actions)) |
| generic relations (`ContentType`) | model each target as its own foreign key ([Entities and migrations](/entities-and-migrations)) |

## Schema adoption

Django names tables `<app>_<model>` and ids are `bigint` (`DEFAULT_AUTO_FIELD`). Phase 1 of the
runbook declares the existing tables with the physical-name overrides it gives, then `x db gen`
until `x verify --only drift` agrees: [Migrating an existing app](/migrating-an-existing-app).

## Identity cutover

| Django stores | Branch |
|---|---|
| `auth_user.password` as `pbkdf2_sha256$…` — Django's default hasher | **⛔ stop**: no PBKDF2 verifier ships, and a row in that scheme never verifies. Keep Django's login as a bridge until every user has signed in once, or force a reset ([Migrating an existing app](/migrating-an-existing-app)) |
| `bcrypt_sha256$…` | **⛔ stop** for the same reason: the prefix is Django's, not a PHC string |
| the session: `django_session` rows keyed by a cookie | bridge it with your own lookup behind `configureAuthenticator()` ([Auth](/auth)) |
