django - 如果 Django-reversion 中没有任何变化,则不要创建新版本

标签 django django-1.8 django-reversion

我想仅在 django-reversion 中发生更改时才保存新对象版本。我浏览了文档并没有找到任何关于它的信息。我怎样才能实现它?

最佳答案

您可以使用 the ignore_duplicates option .很遗憾

It doesn't follow relations, as that can get expensive and slow very quickly.



如果您真的想忽略跟随关系的重复项,您有两种可能性:
  • 做 fork 和禁用限制

  • 删除 and explicit这里https://github.com/etianen/django-reversion/blob/master/reversion/revisions.py#L199

    套装ignore_duplicatesTrue默认 https://github.com/etianen/django-reversion/blob/master/reversion/revisions.py#L368

    小心,如上所述,它可能很慢。
  • the post revision commit signal并手动删除重复版本

  • 套装ignore_duplicatesFalse并添加信号接收器:
    from django.db import transaction
    from django.dispatch import receiver
    from reversion.models import Revision, Version
    from reversion.signals import post_revision_commit
    
    
    def clear_versions(versions, revision):
        count = 0
        for version in versions:
            previous_version = Version.objects.filter(
                object_id=version.object_id,
                content_type_id=version.content_type_id,
                db=version.db,
                id__lt=version.id,
            ).first()
            if not previous_version:
                continue
            if previous_version._local_field_dict == version._local_field_dict:
                version.delete()
                count += 1
            if len(versions_ids) == count:
                revision.delete()
    
    
    @receiver(post_revision_commit)
    def post_revision_commit_receiver(sender, revision, versions, **kwargs):
        transaction.on_commit(lambda: clear_versions(versions, revision))
    

    它也可能很慢,但您可以异步执行(例如,在 Celery 任务中):
    # tasks.py
    
    @celery.task(time_limit=60, ignore_result=True)
    def clear_versions(revision_id, versions_ids):
        count = 0
        if versions_ids:
            for version in Version.objects.filter(id__in=versions_ids):
                previous_version = Version.objects.filter(
                    object_id=version.object_id,
                    content_type_id=version.content_type_id,
                    db=version.db,
                    id__lt=version.id,
                ).first()
                if not previous_version:
                    continue
                if previous_version._local_field_dict == version._local_field_dict:
                    version.delete()
                    count += 1
        if len(versions_ids) == count:
            Revision.objects.only('id').get(id=revision_id).delete()
    
    # signals.py
    
    @receiver(post_revision_commit)
    def post_revision_commit_receiver(sender, revision, versions, **kwargs):
        transaction.on_commit(
            lambda: clear_versions.delay(revision.id, [v.id for v in versions])
        )
    

    关于django - 如果 Django-reversion 中没有任何变化,则不要创建新版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30439461/

    相关文章:

    Django 媒体文件自动删除

    python - Django 多重继承 E005

    django-reversion 及相关模型

    python - 在 Django 中有效地获取相关模型的数量

    python - 无法从我的数据库访问某些信息与 django 的多对多关系

    python - 如何处理 django 表单中的 'auto-now' 字段?

    python - django-reversion 撤消功能 - 恢复多个对象

    django - 为什么 Django 中不再推荐永久链接装饰器?

    python - 在 Django 1.8 中创建自定义查询