看看django-reversion
。它为 Django 模型提供版本控制。可以很容易地添加到现有项目中。
它不采用“当前”指针方法。相反,它会在每次保存对象时对其进行序列化,并将其存储在一个单独的Version
模型中,并使用指向该对象的通用外键。(默认情况下,关系字段被序列化为主键。)此外,它允许以灵活的方式将 s 分组Version
到s 中。Revision
所以你可以做这样的事情:
- 当用户上传 CSV 文件时,只需像往常一样保存更改,但将
@revision.create_on_success
装饰器添加到执行导入的函数中,以便该函数对记录所做的任何更改都将存储在单个修订版下。
- 当用户点击“撤消”时,您只需还原最新版本。
这是如何完成的::
@revision.create_on_success
def import_csv(request, csv):
# Old versions of all objects save()d here will
# belong to single revision.
def undo_last_csv_import(request):
# First, get latest revision saved by this user.
# (Assuming you create revisions only when user imports a CSV
# and do not version control other data.)
revision = Revision.objects.filter(user=request.user)\
.order_by('-date_created')[0]
# And revert it, delete=True means we want to delete
# any newly added records as well
revision.revert(delete=True)
它依赖于您仅在用户导入 CSV 时创建修订的事实。这意味着,如果您还计划对其他数据进行版本控制,那么您将需要实现某种标志,通过该标志您可以获得受最新导入影响的记录。然后您可以通过此标志获取记录,获取最新保存的版本,并还原该版本所属的整个修订。像这样::
def undo_last_csv_import(request):
some_record = Record.objects.by_user(request.user).from_the_last_import()[0]
latest_saved_version_of_some_record = Version.objects.get_for_date(
some_record,
datetime.now(), # The latest saved Version at the moment.
)
# Revert all versions that belong to the same revision
# as the version we got above.
latest_saved_version_of_some_record.revision.revert()
这不是一个漂亮的解决方案,肯定有办法用这个应用程序做得更好。我建议看一下代码以更好地理解它是如何django-reversion
工作的——文档非常好,找不到没有文档字符串的函数。^_^d
(文档也很好,但结果对我来说有点误导,即他们写Version.objects.get_for_date(your_model, date)
,your_model 实际上是一个模型实例。)
更新: django-reversion 得到积极维护,所以不要过多依赖上面的代码,最好查看他们的wiki,了解如何在 django 管理员之外管理版本和修订。例如,已经支持修订注释,这可能会简化一些事情。