Install & Compatibility
Where this runs
tested against v6.3.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.752s · 66.9MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 3.5s · import 0.700s · 67MB
66MB installed
● package 66MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
register
✓ from reversion import register
Decorator for enabling version control on models.
VersionAdmin
✓ from reversion.admin import VersionAdmin
Provides version history and recovery in the Django admin interface.
create_revision
✓ from reversion import create_revision
Context manager or decorator to group changes into a single revision.
get_for_object
✓ from reversion import get_for_object
✗ from reversion.models import Version; Version.objects.get_for_object(obj)
The higher-level `reversion.get_for_object` is generally preferred over direct `Version.objects` queries.
To get started, install `django-reversion` and add it to your `INSTALLED_APPS`. Then, register your models using the `@reversion.register()` decorator or inherit `VersionAdmin` in your `admin.py` for automatic integration. The `create_revision()` context manager or decorator is used to group multiple changes into a single historical revision, and `get_for_object()` allows programmatic access to an object's version history.
import os
# settings.py (simplified for demonstration)
INSTALLED_APPS = [
# ... other apps
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'reversion',
'myapp',
]
# myapp/models.py
from django.db import models
from reversion import register
@register()
class MyModel(models.Model):
name = models.CharField(max_length=100)
value = models.IntegerField(default=0)
def __str__(self):
return self.name
# myapp/admin.py
from django.contrib import admin
from reversion.admin import VersionAdmin
from .models import MyModel
@admin.register(MyModel)
class MyModelAdmin(VersionAdmin):
pass
# Example usage in a view or management command (assuming MyModel is created)
from django.db import transaction
from reversion import create_revision, set_comment
def update_my_model(obj_id, new_name, comment):
with create_revision():
set_comment(comment)
with transaction.atomic():
obj = MyModel.objects.get(id=obj_id)
obj.name = new_name
obj.save()
# Other related model saves can go here within the same revision block
# reversion.add_to_revision(related_obj)
# To retrieve history:
from reversion import get_for_object
my_instance = MyModel.objects.first() # Get an existing instance
if my_instance:
versions = get_for_object(my_instance).order_by('-revision__date_created')
for version in versions:
print(f"Version {version.pk}: {version.field_dict['name']} (Comment: {version.revision.comment}, User: {version.revision.user})")
Debug
Known issues
breakingIn `v6.0.0`, the custom `pre_revision_commit` and `post_revision_commit` signals were removed. Users should now leverage Django's standard `pre_save` and `post_save` signals on the `Revision` model for similar functionality.fixReplace `reversion.signals.pre_revision_commit` or `post_revision_commit` signal connections with Django's `django.db.models.signals.pre_save` or `post_save` signals connected to the `reversion.models.Revision` model.
affects: >=6.0.0
breakingAs of `v5.0.0`, support for Python 3.6 was dropped. The library now officially requires Python 3.9 or later, and Django 4.2 or later, as per `v6.1.0` requirements.fixUpgrade your Python environment to 3.9+ and your Django version to 4.2+ before upgrading to recent `django-reversion` versions.
affects: >=5.0.0 (Python), >=6.1.0 (Django)
gotchaChanges to your model's schema (e.g., removing fields) can lead to `reversion.errors.RevertError: Could not load <Foo: bar> - incompatible version data` when attempting to restore older versions. This is because `django-reversion` stores versions as JSON, and schema migrations do not update this historical data.fixAfter significant model schema changes, it is often necessary to clear out old revision data for the affected models. Adding new fields is usually fine, but removing fields is problematic. Consider creating data migrations to handle or delete incompatible historical data.
affects: All versions
gotchaBulk update operations (e.g., `QuerySet.update()`) do not trigger Django's `post_save` signals, which `django-reversion` relies on to create revisions. Consequently, changes made via bulk operations will not be recorded in version history automatically.fixTo version changes from bulk operations, wrap them explicitly within a `reversion.create_revision()` context manager and manually add affected objects using `reversion.add_to_revision()` if granular control is needed, or iterate and save objects individually.
affects: All versions
gotchaThe `reversion.RegistrationError: class 'myapp.MyModel' has already been registered with Reversion` commonly occurs due to models.py being imported twice, often caused by relative import statements in your codebase.fixConvert all relative import statements in your Django apps to absolute imports to ensure `models.py` files are not unintentionally imported multiple times.
affects: All versions
Errors
Common errors & fixes
reversion.errors.RegistrationError: class 'myapp.MyModel' has already been registered with Reversion
This error occurs when a Django model is registered with `django-reversion` more than once, typically due to relative import statements causing the `models.py` file to be imported multiple times.
fixConvert all relative imports in your codebase to absolute imports to ensure models are registered only once. For example, instead of `from .models import MyModel`, use `from myapp.models import MyModel`.
reversion.errors.RevertError: Could not load <Foo: bar> - incompatible version data
This error happens when the schema of a model changes (e.g., a field is removed) after versions have been stored. `django-reversion` stores versions as JSON, and older JSON data may no longer be compatible with the current model definition during a revert attempt.
fixIf a field was removed, older versions containing that field's data cannot be deserialized. The recommended approach is to either delete the incompatible versions or manually adjust the serialized data if possible, though deleting is more common for problematic older revisions. Schema migrations that add new fields generally do not cause this issue.
TypeError: Model instances without primary key value are unhashable
This error typically arises when `django-reversion` attempts to process a model instance (often a related object within a revision context) that does not yet have a primary key, such as a newly created but unsaved object, or an object that had its primary key removed during a deletion process, making it unhashable in sets used internally by reversion.
fixEnsure that any model instances being tracked or processed within a reversion context (especially related objects) have been saved to the database and thus have a primary key before the reversion context attempts to hash or retrieve them. This can sometimes occur during complex save/delete operations involving related models within a single transaction.
django.core.exceptions.ImproperlyConfigured: Cannot use VersionAdmin with a database that does not support savepoints.
The `VersionAdmin` class in `django-reversion` requires the underlying database to support savepoints for transaction management, which is essential for its rollback and recovery features. This error occurs if the configured database backend does not support them.
fixEnsure you are using a database backend that supports savepoints (e.g., PostgreSQL, SQLite, MySQL with InnoDB). If you are using a non-supporting database, you will need to switch to one that does or avoid using `VersionAdmin` functionality.
django.db.utils.IntegrityError: NOT NULL constraint failed: myapp_mymodel.new_field_id
This `IntegrityError` (or similar foreign key constraint errors) often occurs when attempting to revert to an older version of a model after a schema migration has added new fields with `NOT NULL` constraints without a default value, or when foreign key relationships cannot be satisfied by the old version's data.
fixWhen reverting after schema changes, especially those adding non-nullable fields, you might need to manually ensure that the reverted data conforms to the current schema. This often means providing default values for new non-nullable fields in the old version's data or handling the migration carefully by clearing revision data or using `createinitialrevisions` after migrations.
Upgrade
Version history
6.3.0latest on PyPI · released Jun 12, 2026
Audit
Dependencies
DjangorequiredCore framework dependency, requires Django 4.2 or later.
PythonrequiredRequires Python 3.9 or later.