def _save_revision(versions, user=None, comment="", meta=(), date_created=None, using=None): from reversion.models import Revision # Bail early if there are no objects to save. if not versions: return # Save a new revision. revision = Revision( date_created=date_created, user=user, comment=comment, ) # Save the revision. revision.save(using=using) # Save version models. for version in versions: version.revision = revision version.save(using=using) # Save the meta information. for meta_model, meta_fields in meta: meta_model._default_manager.db_manager(using=using).create( revision=revision, **meta_fields)
def _save_revision(versions, user=None, comment="", meta=(), date_created=None, using=None): from reversion.models import Revision # Only save versions that exist in the database. # Use _base_manager so we don't have problems when _default_manager is overriden model_db_pks = defaultdict(lambda: defaultdict(set)) for version in versions: model_db_pks[version._model][version.db].add(version.object_id) model_db_existing_pks = { model: { db: frozenset( map( force_str, model._base_manager.using(db).filter( pk__in=pks).values_list("pk", flat=True), )) for db, pks in db_pks.items() } for model, db_pks in model_db_pks.items() } versions = [ version for version in versions if version.object_id in model_db_existing_pks[version._model][version.db] ] # Bail early if there are no objects to save. if not versions: return # Save a new revision. revision = Revision( date_created=date_created, user=user, comment=comment, ) # Send the pre_revision_commit signal. pre_revision_commit.send( sender=create_revision, revision=revision, versions=versions, ) # Save the revision. revision.save(using=using) # Save version models. for version in versions: version.revision = revision version.save(using=using) # Save the meta information. for meta_model, meta_fields in meta: meta_model._base_manager.db_manager(using=using).create( revision=revision, **meta_fields) # Send the post_revision_commit signal. post_revision_commit.send( sender=create_revision, revision=revision, versions=versions, )
def update_metric(revision, sender, signal, versions, **kwargs): version2 = versions[0] fields2 = json.loads(version2.serialized_data)[0]['fields'] if version2.content_type_id == ContentType.objects.get_for_model(Probe).id: version1 = Version.objects.get_for_object( Probe.objects.get(id=version2.object_id))[1] # getting old probeversion from the second entry in VersionQuerySet fields1 = json.loads(version1.serialized_data)[0]['fields'] old_probeversion = u'%s (%s)' % (fields1['name'], fields1['version']) # getting new probeversion from the first entry in VersionQuerySet new_probeversion = u'%s (%s)' % (fields2['name'], fields2['version']) metric_pk = Metric.objects.filter( probeversion=old_probeversion).values_list('id', flat=True) ct = ContentType.objects.get_for_model(Metric) vers = list() for pk in metric_pk: instance = Metric.objects.get(id=pk) instance.probeversion = new_probeversion instance.probekey = version2 instance.save() LogEntry.objects.log_action(user_id=revision.user_id, content_type_id=ct.id, object_id=pk, object_repr=instance.__str__(), action_flag=CHANGE, change_message='Changed probeversion.') metric_ver = Version.objects.filter(object_id=pk, content_type_id=ct.id) rev = Revision(date_created=revision.date_created, user_id=revision.user_id, comment='[{"changed": {"fields": [' '"probeversion"]}}]') ver = Version(object_id=str(instance.id), content_type_id=ct.id, format=metric_ver[0].format, serialized_data=metric_ver[0].serialized_data, object_repr=metric_ver[0].object_repr, db='default') rev.save() Revision.objects.filter(pk=rev.id).update( date_created=revision.date_created) ver.revision = rev data = json.loads(metric_ver[0].serialized_data)[0] data['fields']['probeversion'] = new_probeversion data['fields']['probekey'] = version2.id ver.serialized_data = json.dumps([data]) vers.append(ver) Version.objects.bulk_create(vers)
def _save_revision(versions, user=None, comment="", meta=(), date_created=None, using=None): from reversion.models import Revision # Bail early if there are no objects to save. if not versions: return # Save a new revision. with transaction.atomic(using=using): # altered from original. Normally _save_revision is run wintin atomic context revision = Revision( date_created=date_created, user=user, comment=comment, ) # Send the pre_revision_commit signal. pre_revision_commit.send( sender=create_revision, revision=revision, versions=versions, ) # Save the revision. revision.save(using=using) # Save version models. for version in versions: version.revision = revision version.save(using=using) # Save the meta information. for meta_model, meta_fields in meta: meta_model._default_manager.db_manager(using=using).create( revision=revision, **meta_fields ) # Send the post_revision_commit signal. post_revision_commit.send( sender=create_revision, revision=revision, versions=versions, )
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(versions, user=None, comment="", meta=(), date_created=None, using=None): from reversion.models import Revision # Only save versions that exist in the database. # Use _base_manager so we don't have problems when _default_manager is overriden model_db_pks = defaultdict(lambda: defaultdict(set)) for version in versions: model_db_pks[version._model][version.db].add(version.object_id) model_db_existing_pks = { model: { db: frozenset( map( force_str, model._base_manager.using(db).filter( pk__in=pks).values_list("pk", flat=True), )) for db, pks in db_pks.items() } for model, db_pks in model_db_pks.items() } versions = [ version for version in versions if version.object_id in model_db_existing_pks[version._model][version.db] ] # Bail early if there are no objects to save. if not versions: return # Save a new revision. revision = Revision( date_created=date_created, user=user, comment=comment, ) # Send the pre_revision_commit signal. pre_revision_commit.send( sender=create_revision, revision=revision, versions=versions, ) # Save the revision. revision.save(using=using) # Save version models. for version in versions: version.revision = revision version.save(using=using) # Save the meta information. for meta_inst_or_model, meta_fields in meta: # Default meta class and primary key meta_class = meta_inst_or_model pk = None # Add the revision to the fields that will be added/updated meta_fields['revision'] = revision # If the supplied meta_model is an instance, we need to ensure the # correct class is used when updating as well as be able to query # the meta instance properly if isinstance(meta_inst_or_model, (models.Model, )): # Fetch the class used to make the update meta_class = meta_inst_or_model.__class__ pk = meta_inst_or_model.pk # Call update or create meta_class._base_manager.db_manager(using=using).update_or_create( pk=pk, defaults=meta_fields) # Send the post_revision_commit signal. post_revision_commit.send( sender=create_revision, revision=revision, versions=versions, )
def _save_revision(versions, user=None, comment="", meta=(), date_created=None, using=None): from reversion.models import Revision # Only save versions that exist in the database. model_db_pks = defaultdict(lambda: defaultdict(set)) for version in versions: model_db_pks[version._model][version.db].add(version.object_id) model_db_existing_pks = { model: { db: frozenset(map( force_text, model._default_manager.using(db).filter(pk__in=pks).values_list("pk", flat=True), )) for db, pks in db_pks.items() } for model, db_pks in model_db_pks.items() } custom_models = getattr(settings, 'DJANGO_REVISION_CUSTOM_MODELS', False) if custom_models: if hasattr(settings, 'DJANGO_REVISION_EXCLUDED_MODELS'): versions = [ version for version in versions if version._model._meta.object_name not in settings.DJANGO_REVISION_EXCLUDED_MODELS and version.object_id in model_db_existing_pks[version._model][version.db] ] elif hasattr(settings, 'DJANGO_REVISION_ALLOWED_MODELS'): versions = [ version for version in versions if version._model._meta.object_name in settings.DJANGO_REVISION_ALLOWED_MODELS and version.object_id in model_db_existing_pks[version._model][version.db] ] else: raise ImproperlyConfigured( "Using 'DJANGO_REVISION_CUSTOM_MODELS' without either the 'DJANGO_REVISION_EXCLUDED_MODELS' in" " settings or the 'DJANGO_REVISION_ALLOWED_MODELS' in settings is prohibited.") else: versions = [ version for version in versions if version.object_id in model_db_existing_pks[version._model][version.db] ] # Bail early if there are no objects to save. if not versions: return # Save a new revision. revision = Revision( date_created=date_created, user=user, comment=comment, ) # Send the pre_revision_commit signal. pre_revision_commit.send( sender=create_revision, revision=revision, versions=versions, ) # Save the revision. revision.save(using=using) # Save version models. for version in versions: version.revision = revision version.save(using=using) # Save the meta information. for meta_model, meta_fields in meta: meta_model._default_manager.db_manager(using=using).create( revision=revision, **meta_fields ) # Send the post_revision_commit signal. post_revision_commit.send( sender=create_revision, revision=revision, versions=versions, )
def _save_revision(versions, user=None, comment="", meta=(), date_created=None, using=None): from reversion.models import Revision # Only save versions that exist in the database. model_db_pks = defaultdict(lambda: defaultdict(set)) for version in versions: model_db_pks[version._model][version.db].add(version.object_id) model_db_existing_pks = { model: { db: frozenset( map( force_text, model._default_manager.using(db).filter( pk__in=pks).values_list("pk", flat=True), )) for db, pks in db_pks.items() } for model, db_pks in model_db_pks.items() } versions = [ version for version in versions if version.object_id in model_db_existing_pks[version._model][version.db] ] # Bail early if there are no objects to save. if not versions: return # Save a new revision. revision = Revision( date_created=date_created, user=user, comment=comment, ) # Send the pre_revision_commit signal. pre_revision_commit.send( sender=create_revision, revision=revision, versions=versions, ) # Save the revision. revision.save(using=using) # Save version models. # XXX magic numbers because base content needs to be saved before children BASE_CONTENT_TYPE_ID = 18 versions = sorted( versions, key=lambda v: (0 if v.content_type_id == BASE_CONTENT_TYPE_ID else v.content_type_id)) for version in versions: version.revision = revision version.save(using=using) # Save the meta information. for meta_model, meta_fields in meta: meta_model._default_manager.db_manager(using=using).create( revision=revision, **meta_fields) # Send the post_revision_commit signal. post_revision_commit.send( sender=create_revision, revision=revision, versions=versions, )
def _save_revision(versions, user=None, comment="", meta=(), date_created=None, using=None): from reversion.models import Revision # Only save versions that exist in the database. # Use _base_manager so we don't have problems when _default_manager is overriden model_db_pks = defaultdict(lambda: defaultdict(set)) for version in versions: model_db_pks[version._model][version.db].add(version.object_id) def _safe_get_pks(model, db, pks): """ Hack: helper function for use with django-safedelete package so we avoid committing versions for objects that have already been safe deleted See hack in models VersionQuerySet get_deleted too """ try: from safedelete.models import is_safedelete_cls except ImportError: is_safedelete_cls = lambda: False if is_safedelete_cls(model): # Use the safedelete manager to ensure we exclude "soft-deleted" # obj versions return model._default_manager.using(db).filter(pk__in=pks)\ .values_list("pk", flat=True) # Else: not using softdelete for this model so use base manager as in # original django-revision return model._base_manager.using(db).filter(pk__in=pks)\ .values_list("pk", flat=True) model_db_existing_pks = { model: { db: frozenset(map( force_text, _safe_get_pks(model, db, pks), )) for db, pks in db_pks.items() } for model, db_pks in model_db_pks.items() } versions = [ version for version in versions if version.object_id in model_db_existing_pks[version._model][version.db] ] # Bail early if there are no objects to save. if not versions: return # Save a new revision. revision = Revision( date_created=date_created, user=user, comment=comment, ) # Send the pre_revision_commit signal. pre_revision_commit.send( sender=create_revision, revision=revision, versions=versions, ) # Save the revision. revision.save(using=using) # Save version models. for version in versions: version.revision = revision version.save(using=using) # Save the meta information. for meta_model, meta_fields in meta: meta_model._base_manager.db_manager(using=using).create( revision=revision, **meta_fields) # Send the post_revision_commit signal. post_revision_commit.send( sender=create_revision, revision=revision, versions=versions, )