django-reversion API¶
Use the django-reversion API to build version-controlled apps. See also Views and Middleware.
Overview¶
Registering models¶
Models must be registered with django-reversion before they can be used with the API.
from django.db import models
import reversion
@reversion.register()
class YourModel(models.Model):
pass
Hint
If you’re using the Admin integration, model registration is automatic. If you’re using django-reversion in a management command, make sure you call django.contrib.admin.autodiscover() to load the admin modules before using the django-reversion API.
Hint
Whenever you register a model with django-reversion, run createinitialrevisions.
Creating revisions¶
A revision represents one or more changes made to your model instances, grouped together as a single unit. You create a revision by creating a revision block. When you call save() on a registered model inside a revision block, it will be added to that revision.
# Declare a revision block.
with reversion.create_revision():
# Save a new model instance.
obj = YourModel()
obj.name = "obj v1"
obj.save()
# Store some meta-information.
reversion.set_user(request.user)
reversion.set_comment("Created revision 1")
# Declare a new revision block.
with reversion.create_revision():
# Update the model instance.
obj.name = "obj v2"
obj.save()
# Store some meta-information.
reversion.set_user(request.user)
reversion.set_comment("Created revision 2")
Important
Bulk actions, such as Queryset.update(), do not send signals, so won’t be noticed by django-reversion.
Loading revisions¶
Each model instance saved in a revision block is serialized as a reversion.models.Version. All versions in a revision block are associated with a single reversion.models.Revision.
You can load a reversion.models.VersionQuerySet of versions from the database. Versions are loaded with the most recent version first.
from reversion.models import Version
# Load a queryset of versions for a specific model instance.
versions = Version.objects.get_for_object(instance)
assert len(versions) == 2
# Check the serialized data for the first version.
assert versions[1].field_dict["name"] == "obj v1"
# Check the serialized data for the second version.
assert versions[0].field_dict["name"] == "obj v2"
Revision metadata¶
reversion.models.Revision stores meta-information about the revision.
# Check the revision metadata for the first revision.
assert versions[1].revision.comment == "Created revision 1"
assert versions[1].revision.user == request.user
assert isinstance(versions[1].revision.date_created, datetime.datetime)
# Check the revision metadata for the second revision.
assert versions[0].revision.comment == "Created revision 2"
assert versions[0].revision.user == request.user
assert isinstance(versions[0].revision.date_created, datetime.datetime)
Reverting revisions¶
Revert a reversion.models.Revision to restore the serialized model instances.
# Revert the first revision.
versions[1].revision.revert()
# Check the model instance has been reverted.
obj.refresh_from_db()
assert obj.name == "version 1"
# Revert the second revision.
versions[0].revision.revert()
# Check the model instance has been reverted.
obj.refresh_from_db()
assert obj.name == "version 2"
Restoring deleted model instances¶
Reverting a reversion.models.Revision will restore any serialized model instances that have been deleted.
# Delete the model instance, but store the pk.
pk = obj.pk
obj.delete()
# Revert the second revision.
versions[0].revision.revert()
# Check the model has been restored to the database.
obj = YourModel.objects.get(pk=obj.pk)
assert obj.name == "version 2"
Registration API¶
reversion.register(model, **options)
Registers a model with django-reversion.
Throws reversion.RegistrationError if the model has already been registered.
modelThe Django model to register.
fields=NoneAn iterable of field names to include in the serialized data. If
None, all fields will be included.exclude=()An iterable of field names to exclude from the serialized data.
follow=()An iterable of model relationships to follow when saving a version of this model.
ForeignKey,ManyToManyFieldand reversionForeignKeyrelationships are supported. Any property that returns aModelorQuerySetis also supported.format="json"The name of a Django serialization format to use when saving the model instance.
for_concrete_model=TrueIf
Trueproxy models will be saved under the same content type as their concrete model. IfFalse, proxy models will be saved under their own content type, effectively giving proxy models their own distinct history.ignore_duplicates=FalseIf
True, then an additional check is performed to avoid saving duplicate versions for this model.Checking for duplicate revisions adds significant overhead to the process of creating a revision. Don’t enable it unless you really need it!
use_natural_foreign_keys=FalseIf
True, the the model will be serialized using natural keys.Hint
By default, django-reversion will not register any parent classes of a model that uses multi-table inheritance. If you wish to also add parent models to your revision, you must explicitly add their
parent_ptrfields to thefollowparameter when you register the model.Hint
Whenever you register a model with django-reversion, run createinitialrevisions.
reversion.is_registered(model)
Returns whether the given model has been registered with django-reversion.
modelThe Django model to check.
reversion.unregister(model)
Unregisters the given model from django-reversion.
Throws reversion.RegistrationError if the model has not been registered with django-reversion.
modelThe Django model to unregister.
reversion.get_registered_models()
Returns an iterable of all registered models.
Revision API¶
reversion.create_revision(manage_manually=False, using=None, atomic=True)
Marks a block of code as a revision block. Can also be used as a decorator.
manage_manuallyIf
True, versions will not be saved when a model’ssave()method is called. This allows version control to be switched off for a given revision block.usingThe database to save the revision data. The revision block will be wrapped in a transaction using this database. If
None, the default database for reversion.models.Revision will be used.atomicIf
True, the revision block will be wrapped in atransaction.atomic().
reversion.is_active()
Returns whether there is currently an active revision block.
reversion.is_manage_manually()
Returns whether the current revision block is in
manage_manuallymode.
reversion.set_user(user)
Sets the user for the current revision.
Throws reversion.RevisionManagementError if there is no active revision block.
userA
Usermodel instance (or whatever yoursettings.AUTH_USER_MODELis).
reversion.get_user()
Returns the user for the current revision.
Throws reversion.RevisionManagementError if there is no active revision block.
reversion.set_comment(comment)
Sets the comment for the current revision.
Throws reversion.RevisionManagementError if there is no active revision block.
commentThe text comment for the revision.
reversion.get_comment()
Returns the comment for the current revision.
Throws reversion.RevisionManagementError if there is no active revision block.
reversion.set_date_created(date_created)
Sets the creation date for the current revision.
Throws reversion.RevisionManagementError if there is no active revision block.
date_createdThe creation date for the revision.
reversion.get_date_created()
Returns the creation date for the current revision.
Throws reversion.RevisionManagementError if there is no active revision block.
reversion.add_meta(model, **values)
Adds custom metadata to a revision.
Throws reversion.RevisionManagementError if there is no active revision block.
modelA Django model to store the custom metadata. The model must have a
ForeignKeyorOneToOneFieldto reversion.models.Revision.**valuesValues to be stored on
modelwhen it is saved.
reversion.add_to_revision(obj, model_db=None)
Adds a model instance to a revision.
Throws reversion.RevisionManagementError if there is no active revision block.
objA model instance to add to the revision.
model_dbThe database where the model is saved. Defaults to the default database for the model.
reversion.models.VersionQuerySet¶
A QuerySet of reversion.models.Version. The results are ordered with the most recent reversion.models.Version first.
Version.objects.get_for_model(model, model_db=None)
Returns a reversion.models.VersionQuerySet for the given model.
Throws reversion.RegistrationError if the model has not been registered with django-reversion.
modelA registered model.
model_dbThe database where the model is saved. Defaults to the default database for the model.
Version.objects.get_for_object(obj, model_db=None)
Returns a reversion.models.VersionQuerySet for the given model instance.
Throws reversion.RegistrationError if the model has not been registered with django-reversion.
objAn instance of a registered model.
model_dbThe database where the model is saved. Defaults to the default database for the model.
Version.objects.get_for_object_reference(model, pk, model_db=None)
Returns a reversion.models.VersionQuerySet for the given model and primary key.
Throws reversion.RegistrationError if the model has not been registered with django-reversion.
modelA registered model.
pkThe database primary key of a model instance.
model_dbThe database where the model is saved. Defaults to the default database for the model.
Version.objects.get_deleted(model, model_db=None)
Returns a reversion.models.VersionQuerySet for the given model containing versions where the serialized model no longer exists in the database.
Throws reversion.RegistrationError if the model has not been registered with django-reversion.
modelA registered model.
dbThe database to load the versions from.
model_dbThe database where the model is saved. Defaults to the default database for the model.
Version.objects.get_unique()
Returns an iterable of reversion.models.Version, where each version is unique for a given database, model instance, and set of serialized fields.
reversion.models.Version¶
Represents a single model instance serialized in a revision.
Version.id
The database primary key of the reversion.models.Version.
Version.revision
A
ForeignKeyto a reversion.models.Revision instance.
Version.content_type
The
ContentTypeof the serialized model instance.
Version.object_id
The string representation of the serialized model instance’s primary key.
Version.db
The Django database alias where the serialized model was saved.
Version.format
The name of the Django serialization format used to serialize the model instance.
Version.serialized_data
The raw serialized data of the model instance.
Version.object_repr
The stored snapshot of the model instance’s
__str__method when the instance was serialized.
Version.field_dict
A dictionary of stored model fields. This includes fields from any parent models in the same revision.
Throws reversion.RevertError if the model could not be deserialized or reverted, e.g. the serialized data is not compatible with the current database schema.
Version.revert()
Restores the serialized model instance to the database. To restore the entire revision, use Revision.revert().
Throws reversion.RevertError if the model could not be deserialized or reverted, e.g. the serialized data is not compatible with the current database schema.
reversion.models.Revision¶
Contains metadata about a revision, and groups together all reversion.models.Version instances created in that revision.
Revision.id
The database primary key of the reversion.models.Revision.
Revision.date_created
A
datetimewhen the revision was created.
Revision.user
The
Userthat created the revision, or None.
Revision.get_comment()
A text comment on the revision.
Revision.revert(delete=False)
Restores all contained serialized model instances to the database.
Throws reversion.RevertError if the model could not be deserialized or reverted, e.g. the serialized data is not compatible with the current database schema.
deleteIf
True, any model instances which have been created and are reachable by thefollowclause of any model instances in this revision will be deleted. This effectively restores a group of related models to the state they were in when the revision was created.