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