예제 #1
0
 def save_revision(self, objects, ignore_duplicates=False, user=None, comment="", meta=(), db=None):
     """Saves a new revision."""
     # Get the db alias.
     db = db or DEFAULT_DB_ALIAS
     # Adapt the objects to a dict.
     if isinstance(objects, (list, tuple)):
         objects = dict(
             (obj, self.get_adapter(obj.__class__).get_version_data(obj, VERSION_CHANGE, db)) for obj in objects
         )
     # Create the revision.
     if objects:
         # Follow relationships.
         for obj in self._follow_relationships(objects.iterkeys()):
             if not obj in objects:
                 adapter = self.get_adapter(obj.__class__)
                 objects[obj] = adapter.get_version_data(obj, VERSION_CHANGE)
         # Create all the versions without saving them
         ordered_objects = list(objects.iterkeys())
         new_versions = [Version(**objects[obj]) for obj in ordered_objects]
         # Check if there's some change in all the revision's objects.
         save_revision = True
         if ignore_duplicates:
             # Find the latest revision amongst the latest previous version of each object.
             subqueries = [
                 Q(object_id=version.object_id, content_type=version.content_type) for version in new_versions
             ]
             subqueries = reduce(operator.or_, subqueries)
             latest_revision = self._get_versions(db).filter(subqueries).aggregate(Max("revision"))["revision__max"]
             # If we have a latest revision, compare it to the current revision.
             if latest_revision is not None:
                 previous_versions = (
                     self._get_versions(db)
                     .filter(revision=latest_revision)
                     .values_list("serialized_data", flat=True)
                 )
                 if len(previous_versions) == len(new_versions):
                     all_serialized_data = [version.serialized_data for version in new_versions]
                     if sorted(previous_versions) == sorted(all_serialized_data):
                         save_revision = False
         # Only save if we're always saving, or have changes.
         if save_revision:
             # Save a new revision.
             revision = Revision(manager_slug=self._manager_slug, user=user, comment=comment)
             # Send the pre_revision_commit signal.
             pre_revision_commit.send(self, instances=ordered_objects, revision=revision, versions=new_versions)
             # Save the revision.
             revision.save(using=db)
             # Save version models.
             for version in new_versions:
                 version.revision = revision
                 version.save(using=db)
             # Save the meta information.
             for cls, kwargs in meta:
                 cls._default_manager.db_manager(db).create(revision=revision, **kwargs)
             # Send the pre_revision_commit signal.
             post_revision_commit.send(self, instances=ordered_objects, revision=revision, versions=new_versions)
예제 #2
0
    def save_revision(self, objects, user=None, comment='', meta=(), db=None):
        """Saves a new revision."""
        # Create the revision.
        if objects:
            # Follow relationships.
            for obj, follower_type in self._follow_relationships(
                    ((key, version_data.get('type')) for key, version_data in objects.items())
                ):
                if not obj in objects:
                    adapter = self.get_adapter(obj.__class__)
                    follow_obj_data = adapter.get_version_data(obj)
                    follow_obj_data['type'] = follower_type
                    objects[obj] = follow_obj_data

            # Create all the versions without saving them
            ordered_objects = list(objects.keys())
            new_versions = [Version(**objects[obj]) for obj in ordered_objects]
            # Check if there's some change in all the revision's objects.
            save_revision = True
            # Only save if we're always saving, or have changes.
            if save_revision:
                # Save a new revision.
                revision = Revision(
                    manager_slug = self._manager_slug,
                    user = user,
                    comment = comment,
                )
                # Send the pre_revision_commit signal.
                pre_revision_commit.send(self,
                    instances = ordered_objects,
                    revision = revision,
                    versions = new_versions,
                )
                # Save the revision.
                with transaction.atomic(using=db):
                    revision.save(using=db)
                    # Save version models.
                    for version in new_versions:
                        version.revision = revision
                        version.save()
                    # Save the meta information.
                    for cls, kwargs in meta:
                        cls._default_manager.db_manager(db).create(revision=revision, **kwargs)
                # Send the post_revision_commit signal.
                post_revision_commit.send(self,
                    instances = ordered_objects,
                    revision = revision,
                    versions = new_versions,
                )
                # Return the revision.
                return revision
예제 #3
0
 def save_revision(self, objects, ignore_duplicates=False, user=None, comment="", meta=(), db=None):
     """Saves a new revision."""
     # Get the db alias.
     db = db or DEFAULT_DB_ALIAS
     # Adapt the objects to a dict.
     if isinstance(objects, (list, tuple)):
         objects = dict(
             (obj, self.get_adapter(obj.__class__).get_version_data(obj, db))
             for obj in objects
         )
     # Create the revision.
     if objects:
         # Follow relationships.
         for obj in self._follow_relationships(objects.keys()):
             if not obj in objects:
                 adapter = self.get_adapter(obj.__class__)
                 objects[obj] = adapter.get_version_data(obj)
         # Create all the versions without saving them
         ordered_objects = list(objects.keys())
         new_versions = [Version(**objects[obj]) for obj in ordered_objects]
         # Check if there's some change in all the revision's objects.
         save_revision = True
         if ignore_duplicates:
             # Find the latest revision amongst the latest previous version of each object.
             subqueries = [Q(object_id=version.object_id, content_type=version.content_type) for version in new_versions]
             subqueries = reduce(operator.or_, subqueries)
             latest_revision = self._get_versions(db).filter(subqueries).aggregate(Max("revision"))["revision__max"]
             # If we have a latest revision, compare it to the current revision.
             if latest_revision is not None:
                 previous_versions = self._get_versions(db).filter(revision=latest_revision).values_list("serialized_data", flat=True)
                 if len(previous_versions) == len(new_versions):
                     all_serialized_data = [version.serialized_data for version in new_versions]
                     if sorted(previous_versions) == sorted(all_serialized_data):
                         save_revision = False
         # Only save if we're always saving, or have changes.
         if save_revision:
             # Save a new revision.
             revision = Revision(
                 manager_slug = self._manager_slug,
                 user = user,
                 comment = comment,
             )
             # Send the pre_revision_commit signal.
             pre_revision_commit.send(self,
                 instances = ordered_objects,
                 revision = revision,
                 versions = new_versions,
             )
             # Save the revision.
             with transaction.atomic(using=db):
                 revision.save(using=db)
                 # Save version models.
                 for version in new_versions:
                     version.revision = revision
                 Version.objects.using(db).bulk_create(new_versions)
                 # Save the meta information.
                 for cls, kwargs in meta:
                     cls._default_manager.db_manager(db).create(revision=revision, **kwargs)
             # Send the pre_revision_commit signal.
             post_revision_commit.send(self,
                 instances = ordered_objects,
                 revision = revision,
                 versions = new_versions,
             )
             # Return the revision.
             return revision
예제 #4
0
 def save_revision(self, objects, updated=None, inserted=None, deleted=None, ignore_duplicates=False, user=None,
                   comment="", smart=True, meta=(), db=None):
     """Saves a new revision."""
     request = current_task.request
     logger.info("Executing task id {id}, args: {args} retries: {retries}".format(
         id=request.id, args=request.args, retries=request.retries))
     logger.info(request.kwargs)
     # Get the db alias.
     db = db or DEFAULT_DB_ALIAS
     # Adapt the objects to a dict.
     if isinstance(objects, (list, tuple)):
         objects = dict(
             (obj, self.get_adapter(obj.__class__).get_version_data(obj, VERSION_CHANGE, db))
             for obj in objects
         )
     # Create the revision.
     if objects:
         # Follow relationships.
         for obj in self._follow_relationships(objects.keys()):
             if not obj in objects:
                 adapter = self.get_adapter(obj.__class__)
                 objects[obj] = adapter.get_version_data(obj, VERSION_CHANGE)
         # Create all the versions without saving them
         ordered_objects = list(objects.keys())
         new_versions = [Version(**objects[obj]) for obj in ordered_objects]
         # Check if there's some change in all the revision's objects.
         save_revision = True
         if ignore_duplicates:
             # Find the latest revision amongst the latest previous version of each object.
             subqueries = [Q(object_id=version.object_id, content_type=version.content_type)
                           for version in new_versions]
             subqueries = reduce(operator.or_, subqueries)
             latest_revision = self._get_versions(db).filter(subqueries).aggregate(Max("revision"))["revision__max"]
             # If we have a latest revision, compare it to the current revision.
             if latest_revision is not None:
                 previous_versions = (self._get_versions(db).filter(revision=latest_revision)
                                      .values_list("serialized_data", flat=True))
                 if len(previous_versions) == len(new_versions):
                     all_serialized_data = [version.serialized_data for version in new_versions]
                     if sorted(previous_versions) == sorted(all_serialized_data):
                         save_revision = False
         # Only save if we're always saving, or have changes.
         if save_revision:
             # Save a new revision.
             if not comment and smart:
                 deleted_comments, inserted_comments, updated_comments = [], [], []
                 for deleted_instance in deleted:
                     deleted_comments.append(was_deleted_message.format(get_object_smart_repr(deleted_instance)))
                 for inserted_instance in inserted:
                     #here we must get the instances what was created
                     inserted_comments.append(was_created_message.format(get_object_smart_repr(inserted_instance)))
                 for serialized_updated_instance in updated:
                     old_instance_deserialized = deserialize(VersionAdapter.format,
                                                             serialized_updated_instance).next()
                     new_instance = None
                     change_list = []
                     for instance in objects:
                         if (old_instance_deserialized.object.__class__ == instance.__class__
                                 and old_instance_deserialized.object.pk == instance.pk):
                             new_instance = instance
                             break
                     fields = sorted(new_instance._meta.fields + new_instance._meta.many_to_many,
                                     key=lambda x: x.creation_counter)
                     exclude_fields = self.get_adapter(new_instance.__class__).exclude
                     fields = [field for field in fields if field.name not in exclude_fields]
                     for field in fields:
                         old_value, new_value = (field.value_from_object(old_instance_deserialized.object),
                                                 field.value_from_object(new_instance))
                         # Set false old and new values to None because of next != operator(types..)
                         if not old_value:
                             old_value = None
                         if not new_value:
                             new_value = None
                         if old_value != new_value:
                             if not isinstance(field, (AutoField, ManyToManyField)):
                                     if isinstance(field, RelatedField):
                                         if old_value:
                                             value_from = get_object_smart_repr(field.rel.to.objects.get(pk=old_value))
                                         else:
                                             value_from = no_value_message
                                         if new_value:
                                             value_to = get_object_smart_repr(field.rel.to.objects.get(pk=new_value))
                                         else:
                                             value_to = no_value_message
                                         change_list.append(changes_template.format(verbose_name=field.verbose_name,
                                                                                    value_from=value_from,
                                                                                    value_to=value_to))
                                     else:
                                         value_from = old_value if old_value else no_value_message
                                         value_to = new_value if new_value else no_value_message
                                         change_list.append(changes_template.format(verbose_name=field.verbose_name,
                                                                                    value_from=value_from,
                                                                                    value_to=value_to))
                             elif isinstance(field, ManyToManyField):
                                 old_value = old_instance_deserialized.m2m_data[field.name]
                                 old_value = [int(pk) for pk in old_value] if old_value else old_value
                                 new_value = [obj.pk for obj in new_value] if new_value else new_value
                                 if old_value:
                                     value_from = u", ".join(get_object_smart_repr(field.rel.to.objects.get(pk=m2m_pk))
                                                             for m2m_pk in old_value)
                                 else:
                                     value_from = no_value_message
                                 if new_value:
                                     value_to = u", ".join(get_object_smart_repr(field.rel.to.objects.get(pk=m2m_pk))
                                                           for m2m_pk in new_value)
                                 else:
                                     value_to = no_value_message
                                 if old_value != new_value:
                                     change_list.append(changes_template.format(verbose_name=field.verbose_name,
                                                                                value_from=value_from,
                                                                                value_to=value_to))
                     if change_list:
                         object_repr = get_object_smart_repr(old_instance_deserialized.object)
                         change_list.insert(0, was_changed_message.format(object_repr))
                     if change_list:
                         inserted_comments_string = u"\n".join(change_list)
                     else:
                         new_instance_repr = get_object_smart_repr(new_instance)
                         inserted_comments_string = saved_without_changes_message.format(new_instance_repr)
                     inserted_comments.append(inserted_comments_string)
                 comment = u"\n".join(inserted_comments + updated_comments + deleted_comments)
             revision = Revision(
                 manager_slug=self._manager_slug,
                 user=user,
                 user_string=unicode(user) if user else u"",
                 comment=comment,
             )
             # Send the pre_revision_commit signal.
             pre_revision_commit.send(self,
                                      instances=ordered_objects,
                                      revision=revision,
                                      versions=new_versions)
             # Save the revision.
             revision.save(using=db)
             # Save version models.
             for version in new_versions:
                 version.revision = revision
                 version.save(using=db)
             # Save the meta information.
             for cls, kwargs in meta:
                 cls._default_manager.db_manager(db).create(revision=revision, **kwargs)
             # Send the pre_revision_commit signal.
             post_revision_commit.send(self,
                                       instances=ordered_objects,
                                       revision=revision,
                                       versions=new_versions,)
             # Return the revision.
             return revision