如何在Django中实现带版本控制的持久化数据模型?
Hey there! Great question—versioning database records so you can roll back changes is super common, and you’re right that there’s no need to reinvent the wheel here. Let’s break down the best solutions for your use case:
首选方案:用成熟的第三方包
These tools handle all the heavy lifting for you, no messy custom save/delete overrides required.
django-reversion
This is one of the most popular version control packages in the Django ecosystem, and it’s perfect for your needs:
- Automatically tracks every create/update/delete action on your models
- Lets you roll back to any historical version with a few lines of code
- Integrates seamlessly with Django Admin (so you can view/restore versions right in the backend)
- No need to manually rewrite core model methods
Quick setup steps:
- Install it:
pip install django-reversion
- Add it to your
INSTALLED_APPSinsettings.py:
INSTALLED_APPS = [ # ... your other apps 'reversion', ]
- Register your models (two easy options):
- Option 1: Use
VersionAdminin your admin setup:
from django.contrib import admin from reversion.admin import VersionAdmin from .models import YourModel @admin.register(YourModel) class YourModelAdmin(VersionAdmin): pass- Option 2: Use the decorator in your model file (works even if you don’t use Admin):
import reversion from django.db import models from .abstracts import AbstractPersistentModel @reversion.register() class YourModel(AbstractPersistentModel): name = models.CharField(max_length=100) # ... your other fields - Option 1: Use
- Track changes in views (auto-saves versions when you modify objects):
from reversion.views import create_revision def update_model(request, pk): obj = YourModel.objects.get(pk=pk) with create_revision(): obj.name = "Updated Name" obj.save() # Optional: Add a comment to the version reversion.set_comment("Changed name to reflect new branding")
django-simple-history
Another fantastic choice—this one creates a dedicated history table for each of your models, logging every detail of changes (before/after values, who made the change, timestamps). It’s just as easy to use:
Quick setup:
- Install:
pip install django-simple-history
- Add to
INSTALLED_APPS:
INSTALLED_APPS = [ # ... your other apps 'simple_history', ]
- Add the history tracker to your model:
from simple_history.models import HistoricalRecords from django.db import models from .abstracts import AbstractPersistentModel class YourModel(AbstractPersistentModel): name = models.CharField(max_length=100) # Add this field to track history history = HistoricalRecords()
- Run migrations to create the history tables:
python manage.py makemigrations python manage.py migrate
You can then access all historical versions and roll back easily:
# Get all past versions of an object all_versions = obj.history.all() # Roll back to the previous version obj.history.first().instance.save()
If you want a custom (simplified) implementation
If you’d rather avoid third-party packages, you can tweak your abstract model to create version copies on save/delete. Here’s a cleaner approach:
from django.db import models from django.utils.timezone import now class AbstractPersistentModel(models.Model): time_created = models.DateTimeField(auto_now_add=True) time_changed = models.DateTimeField(null=True, default=None) time_deleted = models.DateTimeField(null=True, default=None) is_current = models.BooleanField(default=True) # Marks the latest version class Meta: abstract = True def save(self, *args, **kwargs): if self.pk is not None: # Clone the existing record as a non-current historical version old_instance = self.__class__.objects.get(pk=self.pk) old_instance.pk = None # Generate new primary key old_instance.is_current = False old_instance.time_changed = now() old_instance.save() # Save the new current version self.is_current = True self.time_changed = now() super().save(*args, **kwargs) def delete(self, *args, **kwargs): # Soft delete: mark as deleted and save a historical version self.time_deleted = now() self.save() # Triggers the save logic above to create a history entry
Note that this custom approach has limitations:
- You’ll need to always filter for
is_current=Truewhen fetching active records - No built-in support for tracking which user made changes
- Handling related models gets complicated fast (third-party packages solve this automatically)
Overall, I’d strongly recommend going with django-reversion or django-simple-history—they’re battle-tested, well-documented, and will save you hours of debugging.
内容的提问来源于stack exchange,提问作者Bober

