예제 #1
0
 def revert(self, delete=False):
     """Reverts all objects in this revision."""
     version_set = self.version_set.all()
     # Optionally delete objects no longer in the current revision.
     if delete:
         # Get a dict of all objects in this revision.
         old_revision = {}
         for version in version_set:
             try:
                 obj = version.object
             except ContentType.objects.get_for_id(version.content_type_id).model_class().DoesNotExist:
                 pass
             else:
                 old_revision[obj] = version
         # Calculate the set of all objects that are in the revision now.
         from reversion.revisions import RevisionManager
         current_revision = RevisionManager.get_manager(self.manager_slug)._follow_relationships(old_revision.keys())
         # Delete objects that are no longer in the current revision.
         for item in current_revision:
             if item in old_revision:
                 if old_revision[item].type == VERSION_DELETE:
                     item.delete()
             else:
                 item.delete()
     # Attempt to revert all revisions.
     safe_revert([version for version in version_set if version.type != VERSION_DELETE])
예제 #2
0
 def revert(self, delete=False):
     """Reverts all objects in this revision."""
     version_set = self.version_set.all()
     # Optionally delete objects no longer in the current revision.
     if delete:
         # Get a dict of all objects in this revision.
         old_revision = {}
         for version in version_set:
             try:
                 obj = version.object
             except ContentType.objects.get_for_id(
                     version.content_type_id).model_class().DoesNotExist:
                 pass
             else:
                 old_revision[obj] = version
         # Calculate the set of all objects that are in the revision now.
         from reversion.revisions import RevisionManager
         current_revision = RevisionManager.get_manager(
             self.manager_slug)._follow_relationships(
                 obj for obj in old_revision.keys() if obj is not None)
         # Delete objects that are no longer in the current revision.
         for item in current_revision:
             if item not in old_revision:
                 item.delete()
     # Attempt to revert all revisions.
     safe_revert(version_set)
예제 #3
0
    def revert(self, delete=False):
        """Reverts all objects in this revision."""
        version_set = self.version_set.all()
        # Optionally delete objects no longer in the current revision.
        if delete:
            # Get a dict of all objects in this revision.
            old_revision = set()
            for version in version_set:
                try:
                    obj = version.object
                except ContentType.objects.get_for_id(version.content_type_id).model_class().DoesNotExist:
                    pass
                else:
                    old_revision.add(obj)
            # Calculate the set of all objects that are in the revision now.
            from reversion.revisions import RevisionManager

            current_revision = RevisionManager.get_manager(self.manager_slug)._follow_relationships(
                obj for obj in old_revision if obj is not None
            )
            # Delete objects that are no longer in the current revision.
            for item in current_revision:
                if item not in old_revision:
                    item.delete()
        # Attempt to revert all revisions.
        safe_revert(version_set)
예제 #4
0
 def revert(self, delete=False):
     """Reverts all objects in this revision."""
     version_set = self.version_set.all()
     # Optionally delete objects no longer in the current revision.
     if delete:
         # Get a dict of all objects in this revision.
         old_revision = {}
         for version in version_set:
             try:
                 obj = version.object
             except ContentType.objects.get_for_id(version.content_type_id).model_class().DoesNotExist:
                 pass
             else:
                 old_revision[obj] = version
         # Calculate the set of all objects that are in the revision now.
         from reversion.revisions import RevisionManager
         manager = RevisionManager.get_manager(self.manager_slug)
         current_revision = manager._follow_relationships(obj for obj in old_revision.keys() if obj is not None)
         # Delete objects that are no longer in the current revision.
         for item in current_revision:
             if item._get_pk_val():
                 try:
                     if item in old_revision:
                         if old_revision[item].type == VERSION_DELETE:
                             item.delete()
                     else:
                         item.delete()
                 except (ObjectDoesNotExist, AssertionError):  # assert with Pk none.
                     continue
     # Attempt to revert all revisions.
     versions = [version for version in version_set if version.type != VERSION_DELETE]
     safe_revert(versions)
     reverted.send(sender=self, revision=self, versions=versions)
예제 #5
0
    def revert(self, delete=False):
        """Reverts all objects in this revision."""
        version_set = self.version_set.all()
        # Optionally delete objects no longer in the current revision.
        if delete:
            # Get a dict of all objects in this revision.
            old_revision = {}
            for version in version_set:
                try:
                    obj = version.object
                except ContentType.objects.get_for_id(
                        version.content_type_id).model_class().DoesNotExist:
                    pass
                else:
                    old_revision[obj] = version
            # Calculate the set of all objects that are in the revision now.
            from reversion.revisions import RevisionManager
            current_revision = RevisionManager.get_manager(
                self.manager_slug)._follow_relationships(old_revision.keys())
            # Delete objects that are no longer in the current revision.
            for item in current_revision:
                if item in old_revision:
                    if old_revision[item].type == VERSION_DELETE:
                        item.delete()
                else:
                    item.delete()
        # Attempt to revert all revisions.
        def do_revert(versions):
            unreverted_versions = []
            for version in versions:
                try:
                    version.revert()
                except IntegrityError:
                    unreverted_versions.append(version)
            if len(unreverted_versions) == len(versions):
                raise RevertError(
                    "Could not revert revision, due to database integrity errors."
                )
            if unreverted_versions:
                do_revert(unreverted_versions)

        do_revert([
            version for version in version_set
            if version.type != VERSION_DELETE
        ])
 def handle(self, *app_labels, **options):
     # Activate project's default language
     translation.activate(settings.LANGUAGE_CODE)
     # Load admin classes.
     admin.autodiscover()
     # Parse options.
     comment = options["comment"]
     batch_size = options["batch_size"]
     revision_manager = RevisionManager.get_manager(options["manager"])
     database = options["database"]
     verbosity = int(options.get("verbosity", 1))
     model_classes = parse_app_labels(revision_manager, app_labels)
     # Create revisions.
     with transaction.atomic(using=database):
         for model_class in model_classes:
             self.create_initial_revisions(model_class, comment, batch_size, verbosity, revision_manager, database)
     # Go back to default language
     translation.deactivate()
 def handle(self, *app_labels, **options):
     # Activate project's default language
     translation.activate(settings.LANGUAGE_CODE)
     # Load admin classes.
     admin.autodiscover()
     # Parse options.
     comment = options["comment"]
     batch_size = options["batch_size"]
     revision_manager = RevisionManager.get_manager(options["manager"])
     database = options["database"]
     verbosity = int(options.get("verbosity", 1))
     model_classes = parse_app_labels(revision_manager, app_labels)
     # Create revisions.
     with transaction.atomic(using=database):
         for model_class in model_classes:
             self.create_initial_revisions(model_class, comment, batch_size,
                                           verbosity, revision_manager,
                                           database)
     # Go back to default language
     translation.deactivate()
예제 #8
0
    def object_version(self):
        """The stored version of the model."""
        data = self.serialized_data
        data = force_text(data.encode("utf8"))

        obj = self.object

        reverted_obj = list(
            serializers.deserialize(self.format, data,
                                    ignorenonexistent=True))[0]

        from reversion.revisions import RevisionManager
        manager = RevisionManager.get_manager(self.revision.manager_slug)
        fields = manager.get_adapter(self.content_type.model_class()).fields

        for field in fields:
            setattr(obj, field, getattr(reverted_obj.object, field))

        reverted_obj.object = obj

        return reverted_obj
예제 #9
0
 def revert(self, delete=False):
     """Reverts all objects in this revision."""
     version_set = self.version_set.all()
     # Optionally delete objects no longer in the current revision.
     if delete:
         # Get a dict of all objects in this revision.
         old_revision = {}
         for version in version_set:
             try:
                 obj = version.object
             except ContentType.objects.get_for_id(version.content_type_id).model_class().DoesNotExist:
                 pass
             else:
                 old_revision[obj] = version
         # Calculate the set of all objects that are in the revision now.
         from reversion.revisions import RevisionManager
         current_revision = RevisionManager.get_manager(self.manager_slug)._follow_relationships(old_revision.keys())
         # Delete objects that are no longer in the current revision.
         for item in current_revision:
             if item in old_revision:
                 if old_revision[item].type == VERSION_DELETE:
                     item.delete()
             else:
                 item.delete()
     # Attempt to revert all revisions.
     def do_revert(versions):
         unreverted_versions = []
         for version in versions:
             try:
                 version.revert()
             except IntegrityError:
                 unreverted_versions.append(version)
         if len(unreverted_versions) == len(versions):
             raise RevertError("Could not revert revision, due to database integrity errors.")
         if unreverted_versions:
             do_revert(unreverted_versions)
     do_revert([version for version in version_set if version.type != VERSION_DELETE])
예제 #10
0
 def revision_manager(self):
     return RevisionManager.get_manager(self.manager_slug)
예제 #11
0
 def handle(self, *app_labels, **options):
     days = options["days"]
     keep = options["keep"]
     force = options["force"]
     interactive = options["interactive"]
     # Load admin classes.
     admin.autodiscover()
     # Check for deprecated confirmation option.
     if not options["confirmation"]:
         interactive = False
         warnings.warn(
             (
                 "--no-confirmation is deprecated, please use --no-input instead. "
                 "--no-confirmation will be removed in django-reversion 1.12.0"
             ),
             DeprecationWarning
         )
     revision_manager = RevisionManager.get_manager(options["manager"])
     database = options.get("database")
     verbosity = int(options.get("verbosity", 1))
     # Parse date.
     date = None
     if options["date"]:
         if days:
             raise CommandError("You cannot use --date and --days at the same time. They are exclusive.")
         try:
             date = datetime.datetime.strptime(options["date"], "%Y-%m-%d").date()
         except ValueError:
             raise CommandError((
                 "The date you gave (%s) is not a valid date. ",
                 "The date should be in the ISO format (YYYY-MM-DD)."
             ) % options["date"])
     # Find the date from the days arguments.
     elif days:
         date = datetime.date.today() - datetime.timedelta(days)
     # Build the queries
     revision_query = Revision.objects.using(database).filter(
         manager_slug=revision_manager._manager_slug,
     )
     if date:
         revision_query = revision_query.filter(date_created__lt=date)
     if app_labels:
         model_classes = parse_app_labels(revision_manager, app_labels)
         content_types = [
             revision_manager._get_content_type(model_class, db=database)
             for model_class
             in model_classes
         ]
         revision_query = revision_query.filter(version__content_type__in=content_types)
         if not force:
             excluded_content_types = ContentType.objects.db_manager(database).exclude(pk__in=[
                 content_type.pk
                 for content_type
                 in content_types
             ])
             revision_query = revision_query.exclude(version__content_type__in=excluded_content_types)
     # Handle keeping n versions.
     if keep:
         objs = Version.objects.using(database).filter(
             revision__manager_slug=revision_manager._manager_slug,
             revision__in=revision_query,
         )
         # Get all the objects that have more than the maximum revisions.
         objs = objs.values("object_id", "content_type_id", "db").annotate(
             total_ver=Count("object_id"),
         ).filter(total_ver__gt=keep)
         # Get all ids of the oldest revisions minus the max allowed revisions for all objects.
         revisions_not_kept = set()
         for obj in objs:
             revisions_not_kept.update(list(Version.objects.using(database).filter(
                 content_type__id=obj["content_type_id"],
                 object_id=obj["object_id"],
                 db=obj["db"],
             ).order_by("-pk").values_list("revision_id", flat=True)[keep:]))
         revision_query = revision_query.filter(pk__in=revisions_not_kept)
     revision_count = revision_query.count()
     # Ask confirmation
     if interactive:
         choice = input("Are you sure you want to delete %s revisions? [y|N] " % revision_count)
         if choice.lower() != "y":
             self.stdout.write("Aborting revision deletion.")
             return
     # Delete versions and revisions
     if verbosity >= 2:
         self.stdout.write("Deleting %s revisions..." % revision_count)
     # Delete the revisions.
     with transaction.atomic(using=database):
         revision_query.delete()
     # Final logging.
     if verbosity >= 2:
         self.stdout.write("Deleted %s revisions." % revision_count)