Generate goose-style SQL migrations from Django migrations, plus base model mixins
Project description
DJM
CLI and helpers to go from Django models → goose-style SQL migrations (up/down). One app (djm): write your models there, then generate SQL for goose or golang-migrate.
Quick start (CLI)
-
Install and create a project:
pip install djm djm init myapp cd myapp
-
Write your models in the
djmapp (editdjm/models/), then run migrations:uv sync # or: pip install -e . uv run python manage.py makemigrations djm uv run python manage.py migrate
-
Generate goose SQL (up/down) into
goose_migrations/:uv run python manage.py generate_goose
From a project that has the
djmCLI installed you can instead run:djm goose -
Use the generated
.sqlfiles with goose or golang-migrate.
Requirements
- Python ≥3.13 (or adjust in
pyproject.toml) - Django ≥6.0
- uv (recommended) or pip
CLI
| Command | Description |
|---|---|
djm init [path] |
Create a new DJM project (default: current directory). Preconfigured with djm app and generate_goose command. |
djm goose [-o DIR] |
Generate goose SQL migrations (run from project root; uses manage.py generate_goose). |
Project layout (after djm init)
| Path | Purpose |
|---|---|
| djm/ | The only app: write your models here. Includes the generate_goose management command. |
| base/ | Reusable abstract model mixins: UUIDPrimaryKeyMixin, TimestampsMixin, SoftDeleteMixin, SortNumberMixin. |
| core/ | Main Django project (settings, urls). |
Commands (inside a project)
- Generate goose migrations:
uv run python manage.py generate_goose [--output-dir DIR] [--no-sql-extension]
Uses thedjmapp. Default output dir isgoose_migrations. Files are named{migration_name}.sql.
Base mixins
Use these in your models (see djm.models and base.models):
- UUIDPrimaryKeyMixin – UUID primary key (via
uuid6). - TimestampsMixin –
created,updated(auto_now_add / auto_now). - SoftDeleteMixin –
deletednullable datetime for soft deletes. - SortNumberMixin –
order_noand default ordering.
Import from base.models; the mixins are abstract and do not require base in INSTALLED_APPS unless you add migrations in base.
Shipping as a package
The package ships djm (models + generate_goose command) and base (mixins). One app only; users write models in djm.
- Install:
pip install -e /path/to/djmorpip install djm - In the consuming project: Add
djmtoINSTALLED_APPS, write models indjm, runpython manage.py generate_goose -o your_goose_dir. - Build:
make buildoruv build
Publishing to PyPI (GitHub Actions)
The repo includes a workflow that builds and publishes to PyPI when you create a GitHub Release (or run it manually from the Actions tab).
-
One-time: Add a trusted publisher on PyPI:
- PyPI project name:
djm - Repository:
OWNER/djm - Workflow name:
publish.yml
- PyPI project name:
-
To release: Create a new release on GitHub (tag, e.g.
v0.1.0). The workflow will build and publish the package to PyPI. No API token is needed (OIDC).
.github/workflows/publish.yml– build + publish to PyPI on release.github/workflows/ci.yml– build only on push/PR tomain
Makefile
make help– show targetsmake migrate– run Django migrationsmake goose– generate goose SQL intogoose_migrationsmake goose OUT=./sql– generate into./sqlmake clean– remove generated goose files and__pycache__make install–uv syncmake build– build distribution artifacts
Notes
- Django’s
sqlmigratesupports--backwards(with an “s”) to print SQL that unapplies a migration; the generator uses this for the “Down” section. - Generated SQL is for the database configured in
settings.DATABASES["default"](e.g. SQLite). For PostgreSQL/MySQL, run the generator with that database configured.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file djm-0.0.1a0.tar.gz.
File metadata
- Download URL: djm-0.0.1a0.tar.gz
- Upload date:
- Size: 10.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe492e6f96ca962e6ea9dd42da2c01bfd5ef6a0c8e9fd99c689207bf0916d29f
|
|
| MD5 |
7a24395bc1297bf9bb3c9057fd2de56b
|
|
| BLAKE2b-256 |
1d74f45ccdeffce78761a047bd8547c98ce85ab9d017f6608ee1f01b64d42b10
|
Provenance
The following attestation bundles were made for djm-0.0.1a0.tar.gz:
Publisher:
publish.yml on dcostersabin/djm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
djm-0.0.1a0.tar.gz -
Subject digest:
fe492e6f96ca962e6ea9dd42da2c01bfd5ef6a0c8e9fd99c689207bf0916d29f - Sigstore transparency entry: 1004143956
- Sigstore integration time:
-
Permalink:
dcostersabin/djm@8a74ffc6de5276c7197ca83d70d3bb48ce520e25 -
Branch / Tag:
refs/tags/v0.0.1-alpha - Owner: https://github.com/dcostersabin
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a74ffc6de5276c7197ca83d70d3bb48ce520e25 -
Trigger Event:
release
-
Statement type:
File details
Details for the file djm-0.0.1a0-py3-none-any.whl.
File metadata
- Download URL: djm-0.0.1a0-py3-none-any.whl
- Upload date:
- Size: 17.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05cad7051785d21754f64f2c55ea1b114b91ab29181f51deed42b9504dcdd4fd
|
|
| MD5 |
13a163a52b559a58244e24cfb9682eaa
|
|
| BLAKE2b-256 |
78331be39a3cf8007b4f43d9dc1a272e4053fa74febdb8649a47295c3d5e08ea
|
Provenance
The following attestation bundles were made for djm-0.0.1a0-py3-none-any.whl:
Publisher:
publish.yml on dcostersabin/djm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
djm-0.0.1a0-py3-none-any.whl -
Subject digest:
05cad7051785d21754f64f2c55ea1b114b91ab29181f51deed42b9504dcdd4fd - Sigstore transparency entry: 1004143959
- Sigstore integration time:
-
Permalink:
dcostersabin/djm@8a74ffc6de5276c7197ca83d70d3bb48ce520e25 -
Branch / Tag:
refs/tags/v0.0.1-alpha - Owner: https://github.com/dcostersabin
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8a74ffc6de5276c7197ca83d70d3bb48ce520e25 -
Trigger Event:
release
-
Statement type: