Skip to main content

Drop-in versioning for Django models — releases, data status workflow, and CI integration

Project description

django-versioned-models

PyPI version Python Development Status Maintenance PyPI License


django-versioned-models

Drop-in versioning for Django models. Every model that inherits from VersionedModel gets full release management, data status workflow, and CI integration — automatically.


🚀 Features

  • Release management - every row in every table is tagged to a release. Branch, lock, patch, and deprecate with simple commands.
  • Data status workflow - DRAFT → FUTURE → APPROVED. CI only sees approved rows. Live edits by architects never break tests.
  • Lock enforcement - locked releases are immutable at the model level. No edits, no deletes, from anywhere — Admin, API, or shell.
  • Auto-discovery - inherit VersionedModel and your model is versioned. No registration needed, no matter how many models.
  • Topological FK sort - when copying a release, models are duplicated in the correct dependency order automatically.
  • Soft deprecation - old releases are hidden by default but data is always preserved and fully reversible.
  • Standalone releases - create a release with no source for bootstrapping a new project or parallel versioning.
  • CI-ready commands - create_release, approve_release, lock_release and more, ready to plug into any pipeline.

Installation

pip install django-versioned-models

Quick Start

1. Add to INSTALLED_APPS

INSTALLED_APPS = [
    ...
    'django_versioned_models',
]

2. Run migrations

python manage.py migrate

3. Create your models

from django_versioned_models.mixins import VersionedModel

class MyModel(VersionedModel):
    name = models.CharField(max_length=255)

    class Meta:
        unique_together = [('release', 'name')]  # unique per release, not globally

4. Run migrations for your models

python manage.py makemigrations
python manage.py migrate

5. Create the first release

python manage.py create_release --release-version v1.0.0

6. Add data, then lock

# Add data via Admin or API...

python manage.py lock_release --release-version v1.0.0

Ongoing Flow

# Create a new release branched from the previous one
python manage.py create_release --release-version v1.1.0 --based-on v1.0.0

# Architects edit data (status=DRAFT by default)

# CI approves stable rows
python manage.py approve_release --release-version v1.1.0

# Run tests against approved data only
pytest --release-version v1.1.0

# Lock and ship
python manage.py lock_release --release-version v1.1.0

# Bug found after deployment? Create a patch — never modify a locked release
python manage.py create_release --release-version v1.1.1 --based-on v1.1.0

How It Works

Every model that inherits from VersionedModel gets two fields added automatically:

  • release — which version this row belongs to
  • status — data readiness (draft / future / approved)

Data Status Workflow

DRAFT <-> FUTURE -> APPROVED  (one-way, CI only)
Status Who Meaning
DRAFT Architects Being worked on
FUTURE Architects Planned for a future release
APPROVED CI only Stable — what tests run against

CI always queries approved rows. DRAFT and FUTURE are invisible to CI — live edits never break tests.

MyModel.objects.approved(release)     # CI — stable rows only
MyModel.objects.for_release(release)  # everyone — all statuses

Lock Enforcement

Locked releases are immutable. Any attempt to save or delete a row in a locked release raises a ValidationError — from the Admin, the API, the shell, anywhere.

# This will raise ValidationError if release is locked
my_instance.save()
my_instance.delete()

Auto-Discovery

All models that inherit from VersionedModel are discovered automatically on every create_release. No manual registration needed. FK dependencies are resolved via topological sort — no ordering required.


Management Commands

Command Description
create_release --release-version v1.0.0 Create a standalone release (unlocked)
create_release --release-version v1.1.0 --based-on v1.0.0 Branch from a locked release
approve_release --release-version v1.1.0 Approve all DRAFT rows (CI only — FUTURE untouched)
lock_release --release-version v1.1.0 Lock a release (immutable)
unlock_release --release-version v1.1.0 Unlock (only before deployment)
deprecate_release --release-version v1.0.0 Soft-delete (data preserved, hidden by default)
deprecate_release --release-version v1.0.0 --undo Restore a deprecated release

Querying

from django_versioned_models.models import Release

release = Release.objects.get(version='v1.1.0')

# All rows for a release
MyModel.objects.for_release(release)

# Approved rows only (CI)
MyModel.objects.approved(release)

# Filter by status
MyModel.objects.filter(release=release, status='future')

Imports Reference

from django_versioned_models.mixins import VersionedModel, DataStatus
from django_versioned_models.models import Release
from django_versioned_models.services import (
    get_versioned_models,
    get_versioned_models_ordered,
    create_release,
    lock_release,
)

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

django_versioned_models-0.1.0.tar.gz (9.9 kB view details)

Uploaded Source

Built Distribution

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

django_versioned_models-0.1.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file django_versioned_models-0.1.0.tar.gz.

File metadata

  • Download URL: django_versioned_models-0.1.0.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for django_versioned_models-0.1.0.tar.gz
Algorithm Hash digest
SHA256 06e0b02787b5ace38cc84eb484d8e973e70233653cc0e3e579abe66dca28cdd9
MD5 abb97fbe09b2aee0176325f6c2485663
BLAKE2b-256 7272facf778d1abc109f0615cd3e7a42b18675a7acf7e664abc6b41924a6340c

See more details on using hashes here.

File details

Details for the file django_versioned_models-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_versioned_models-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d25207a6d677629381c2a6476a60a9e9623705ec8fd8b9a1ff6cf0da92278b70
MD5 1ee25c0fe965ad1d9e9deec326153617
BLAKE2b-256 dd610cfdf51c05cdc14b5c6b40243f492a05e794d41de2db7e80ab9710309377

See more details on using hashes here.

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