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

时间:2015-05-25 13:23:30

标签: django django-1.8 django-reversion

我想在django-reversion中保存新的对象版本。我查看了文档并没有找到任何相关信息。我怎样才能实现它?

1 个答案:

答案 0 :(得分:1)

您可以使用the ignore_duplicates option。不幸的是

  

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

如果你真的想忽略后续关系的重复,你有两种可能:

  1. 执行fork并禁用限制
  2. 在此处移除and explicit https://github.com/etianen/django-reversion/blob/master/reversion/revisions.py#L199

    默认情况下将ignore_duplicates设为True https://github.com/etianen/django-reversion/blob/master/reversion/revisions.py#L368

    小心,如上所述它可能很慢。

    1. 聆听the post revision commit signal并手动删除重复版本
    2. ignore_duplicates设为False并添加信号接收器:

      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])
          )