Skip to main content

Generate goose-style SQL migrations from Django migrations, plus base model mixins

Project description

DJM

Generate SQL migrations from Django models for goose, golang-migrate, SQLx (Rust), or Diesel (Rust). One app: define models in djm, run Django migrations, then export to SQL.

Why

I build a lot of POCs in Django. When one works and needs to turn into something with real business impact, I usually rewrite in Go or Rust. I only want to rewrite the business logic—not waste time turning existing tables into SQL migrations by hand. DJM exports the schema from Django so I can drop it into a Go (goose) or Rust (SQLx, Diesel) project and focus on the code that matters.

Requirements

  • Python ≥3.13
  • Django ≥6.0

Quick start

pip install djm
djm init myapp
cd myapp

Edit models in djm/models/, then:

pip install -e .   # or: uv sync
python manage.py makemigrations djm
python manage.py migrate
python manage.py goose   # or: python manage.py sqlx, or: python manage.py diesel

Use the generated SQL with your migration tool (goose, golang-migrate, SQLx, or Diesel).

CLI

Command Description
djm init [path] Create a new project (default: current directory).
djm goose [-o DIR] Generate goose-style SQL (default: migrations).
djm sqlx [-o DIR] Generate SQLx-style SQL (default: migrations).
djm diesel [-o DIR] Generate Diesel CLI migrations (default: migrations).

Run djm goose, djm sqlx, and djm diesel from the project root (where manage.py is).

Project layout (after djm init)

Path Purpose
djm/ App for your models; includes goose, sqlx, and diesel management commands.
base/ Abstract mixins: UUIDPrimaryKeyMixin, TimestampsMixin, SoftDeleteMixin, SortNumberMixin.
core/ Django project (settings, urls).

Generating SQL

Goose (one file per migration, up/down in one file):

python manage.py goose [--output-dir DIR] [--no-sql-extension]

SQLx (sqlx-cli reversible format: .up.sql and .down.sql per migration):

python manage.py sqlx [--output-dir DIR] [--no-sql-extension]

Diesel (Diesel CLI: one subdirectory per migration with up.sql and down.sql):

python manage.py diesel [--output-dir DIR]

Output is migrations/<name>/up.sql and migrations/<name>/down.sql. Use with diesel migration run and diesel migration redo.

All commands default to the same dir (migrations). Each marks the directory so the others won’t overwrite it. Use different --output-dir values if you generate for more than one tool (e.g. goose -o goose_migrations, diesel -o diesel_migrations).

Base mixins

Import from base.models:

  • UUIDPrimaryKeyMixin – UUID primary key (uuid6).
  • TimestampsMixincreated, updated.
  • SoftDeleteMixindeleted (nullable datetime).
  • SortNumberMixinorder_no and default ordering.

Mixins are abstract; you don’t need base in INSTALLED_APPS unless you add migrations there.

Makefile

From project root:

  • make help – list targets
  • make install – install dependencies (uv sync)
  • make migrate – apply Django migrations
  • make goose – generate goose SQL (default: migrations)
  • make sqlx – generate SQLx SQL (default: migrations)
  • make diesel – generate Diesel CLI migrations (default: migrations)
  • make test – run tests
  • make clean – remove generated SQL and __pycache__
  • make build – build wheel/sdist

Use make goose OUT=dir, make sqlx OUT=dir, or make diesel OUT=dir to override the output directory.

Development

From the repo:

pip install -e .
python manage.py test djm

Notes

  • SQL is generated for the database in settings.DATABASES["default"]. Use PostgreSQL/MySQL in settings if you need that dialect.
  • Down migrations use Django’s sqlmigrate --backwards under the hood.

Credits

This project was largely built with AI. I wrote only the initial rough version that generated SQL; the rest—SQLx support, refactors, tests, CLI, and docs—came from iterating with AI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

djm-0.0.3a0.tar.gz (17.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

djm-0.0.3a0-py3-none-any.whl (26.6 kB view details)

Uploaded Python 3

File details

Details for the file djm-0.0.3a0.tar.gz.

File metadata

  • Download URL: djm-0.0.3a0.tar.gz
  • Upload date:
  • Size: 17.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for djm-0.0.3a0.tar.gz
Algorithm Hash digest
SHA256 66ea298187dfc91b549e5e714a67ec9b1c02d5ac9f5fb6497aa11ff6ae87d7d9
MD5 73aa373578c07bcbd529a770d4eb992b
BLAKE2b-256 fcf4ae7044a59f94072ae8340cdc220ec0e5e3afad373ac5ff4bcbdb02762f87

See more details on using hashes here.

Provenance

The following attestation bundles were made for djm-0.0.3a0.tar.gz:

Publisher: publish.yml on dcostersabin/djm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file djm-0.0.3a0-py3-none-any.whl.

File metadata

  • Download URL: djm-0.0.3a0-py3-none-any.whl
  • Upload date:
  • Size: 26.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for djm-0.0.3a0-py3-none-any.whl
Algorithm Hash digest
SHA256 40b8e61c79e34ace7fc13c048d053a824cb7ad191ca2cf030373c39e372d45aa
MD5 4b4cfa4ce0b29ae890dcd18d23fb781b
BLAKE2b-256 e79f57b820028debf5c8714ee0e7c3a937f4882795ec71500511e59e3847bf5d

See more details on using hashes here.

Provenance

The following attestation bundles were made for djm-0.0.3a0-py3-none-any.whl:

Publisher: publish.yml on dcostersabin/djm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page