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, or SQLx (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) 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

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

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).

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

Project layout (after djm init)

Path Purpose
djm/ App for your models; includes goose and sqlx 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]

Both commands write into the same default dir (migrations). Each marks the directory so the other won’t overwrite it. To use both, use different dirs (e.g. goose -o goose_migrations, sqlx keeps 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 test – run tests
  • make clean – remove generated SQL and __pycache__
  • make build – build wheel/sdist

Use make goose OUT=dir or make sqlx 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.2a0.tar.gz (14.9 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.2a0-py3-none-any.whl (24.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: djm-0.0.2a0.tar.gz
  • Upload date:
  • Size: 14.9 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.2a0.tar.gz
Algorithm Hash digest
SHA256 5e719563ec316fc3d156f95d972e2ef77a747af71e0b9baba4b7878c1c4d78b5
MD5 aeb6854c3b7fceb133b516c1f0e1345d
BLAKE2b-256 1c0472aa72dd96e93c231cbac790af27b3a89b7d64de01ce2a0e7b99b4831477

See more details on using hashes here.

Provenance

The following attestation bundles were made for djm-0.0.2a0.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.2a0-py3-none-any.whl.

File metadata

  • Download URL: djm-0.0.2a0-py3-none-any.whl
  • Upload date:
  • Size: 24.8 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.2a0-py3-none-any.whl
Algorithm Hash digest
SHA256 801b9d042314afff80c603ad462411fcd8f017ce4db0f7edd378e800c5d7152c
MD5 9ce73a4ae9b0894b9442e12b0dda1301
BLAKE2b-256 56fc5a6fbb991ea0c51361bda0f37e59d1b8960efb726aa4affac5ddff33a75a

See more details on using hashes here.

Provenance

The following attestation bundles were made for djm-0.0.2a0-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