Skip to main content

A robust, elegant and ultra-performance Django model versioning package for Django 4.x+

Project description

📚 Django Model Snapshots

Simple, efficient and intuitive version control for your Django models.

Documentation Tests Coverage Python Django

Full Documentation: https://jotauses.github.io/django-model-snapshots/

📋 Requirements

  • Python: 3.10, 3.11, 3.12, 3.13, 3.14
  • Django: 4.2 (LTS), 5.0, 5.1, 5.2

🌟 Why Django Model Snapshots?

Tracking changes in your database shouldn't be a headache. You need a solution that is:

  • Zero Config: Just add a mixin and you're done.
  • Ultra Efficient: Optimized queries and bulk operations support.
  • Flexible: Automatic by default, but fully controllable when you need it.
  • Developer Friendly: Type-hinted, intuitive API (as_of, between).

🚀 Quick Start

1. Installation

pip install django-model-snapshots

2. Add to your App

Add django_model_snapshots to your INSTALLED_APPS:

# settings.py
INSTALLED_APPS = [
    ...
    'django_model_snapshots',
    ...
]

3. Enable Versioning

Inherit from VersionableMixin in your model. That's it!

from django.db import models
from django_model_snapshots import VersionableMixin

class Product(VersionableMixin, models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)

Now, every time you save() or delete() a Product, a historical record is created automatically.


📖 Usage Guide

Accessing History

Every versioned object gets a .history property. It's like a super-powered QuerySet.

product = Product.objects.get(id=1)

# Get all versions
all_versions = product.history.all()

# Get the latest version
latest = product.history.latest()

# Get the earliest version
original = product.history.earliest()

🕰️ Time Travel (Efficient Querying)

Stop writing complex date filters. Use our intuitive API:

from django.utils import timezone
from datetime import timedelta

# What did this product look like yesterday?
yesterday = timezone.now() - timedelta(days=1)
old_version = product.history.as_of(yesterday)

# Get all changes made last week
start = timezone.now() - timedelta(weeks=1)
end = timezone.now()
changes = product.history.between(start, end)

🎮 Manual Control

Sometimes you don't want to save every single keystroke. We give you full control.

Disable Automatic Versioning:

class DraftPost(VersionableMixin, models.Model):
    title = models.CharField(max_length=100)
    
    # Disable auto-versioning for this model
    VERSIONING_AUTO = False 

Force Versioning on Demand:

Use the force_versioning context manager to create a version explicitly, even if VERSIONING_AUTO is False.

from django_model_snapshots import force_versioning

post = DraftPost.objects.create(title="Draft") # No version created

# Make a major change and record it
with force_versioning():
    post.title = "Published"
    post.save() # Version created!

⚡ Performance & Bulk Operations

Creating thousands of records? Don't kill your database. Use bulk_create_history.

from django_model_snapshots import bulk_create_history

products = [Product(name=f"Product {i}") for i in range(1000)]

# 1. Bulk create the main objects
Product.objects.bulk_create(products)

# 2. Bulk create their history (1 query!)
bulk_create_history(products)

🛠️ Configuration

Select Specific Fields:

By default, all fields are versioned. To save space, specify only what you need:

class UserProfile(VersionableMixin, models.Model):
    bio = models.TextField()
    last_login = models.DateTimeField() # We might not want to version this
    
    # Only version the bio
    versioning_fields = ["bio"]

👮 Admin Integration

View history directly in the Django Admin.

from django.contrib import admin
from django_model_snapshots import VersionAdmin
from .models import Product

@admin.register(Product)
class ProductAdmin(VersionAdmin):
    list_display = ("name", "price")

This adds a "History" button to the admin change view.


🧪 Running Tests

We use pytest for a robust testing suite.

# Run all tests
pytest

# Run with coverage
pytest --cov=django_model_snapshots

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the project
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Built for engineers who care about speed, clean code and type safety ❤️ by Joaquín Vázquez

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_model_snapshots-0.1.0.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

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

django_model_snapshots-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: django_model_snapshots-0.1.0.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for django_model_snapshots-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e57f34de8db8e6ed886e16e9584d823e8c136fa6fa587d047bb6b8f4e0503a49
MD5 da59f16675eeb0f58b05398ed386f033
BLAKE2b-256 57338c61245f36bae5fefbfb2aa5364b5a739090b43d947f4a24e9666a80ce25

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_model_snapshots-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 37f7676d363d14cbdf26671f5c46a0a31045326912a76a3729a08dadcc7c1eeb
MD5 8ba8b30f2fc43cc9ffac445895f3ec45
BLAKE2b-256 ebc76c7934a9bd9f97c4df080cf94219febdf5c05ad59571ac746e651193dd44

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