Ejemplo n.º 1
0
 def get_deleted(self, model_class):
     """
     Returns all the deleted versions for the given model class.
     
     The results are returned with the most recent versions first.
     """
     content_type = ContentType.objects.get_for_model(model_class)
     live_pk_queryset = model_class._default_manager.all().values_list("pk", flat=True)
     versioned_objs = self._get_versions().filter(content_type=content_type)
     if has_int_pk(model_class):
         # We can do this as a fast, in-database join.
         deleted_version_pks = versioned_objs.exclude(object_id_int__in=live_pk_queryset).values_list(
             "object_id_int"
         )
     else:
         # This join has to be done as two separate queries.
         deleted_version_pks = versioned_objs.exclude(object_id__in=list(live_pk_queryset.iterator())).values_list(
             "object_id"
         )
     deleted_version_pks = (
         deleted_version_pks.exclude(type=VERSION_DELETE)
         .annotate(latest_pk=Max("pk"))
         .values_list("latest_pk", flat=True)
     )
     return self._get_versions().filter(pk__in=deleted_version_pks).order_by("-pk")
Ejemplo n.º 2
0
 def get_deleted(self, model_class, db=None, model_db=None):
     """
     Returns all the deleted versions for the given model class.
     
     The results are returned with the most recent versions first.
     """
     db = db or DEFAULT_DB_ALIAS
     model_db = model_db or db
     content_type = ContentType.objects.db_manager(db).get_for_model(model_class)
     live_pk_queryset = model_class._default_manager.db_manager(model_db).all().values_list("pk", flat=True)
     versioned_objs = self._get_versions(db).filter(
         content_type = content_type,
     )
     if has_int_pk(model_class):
         # If the model and version data are in different databases, decouple the queries.
         if model_db != db:
             live_pk_queryset = list(live_pk_queryset.iterator())
         # We can do this as a fast, in-database join.
         deleted_version_pks = versioned_objs.exclude(
             object_id_int__in = live_pk_queryset
         ).values_list("object_id_int")
     else:
         # This join has to be done as two separate queries.
         deleted_version_pks = versioned_objs.exclude(
             object_id__in = list(live_pk_queryset.iterator())
         ).values_list("object_id")
     deleted_version_pks = deleted_version_pks.annotate(
         latest_pk = Max("pk")
     ).values_list("latest_pk", flat=True)
     # HACK: MySQL deals extremely badly with this as a subquery, and can hang infinitely.
     # TODO: If a version is identified where this bug no longer applies, we can add a version specifier.
     if connection.vendor == "mysql":
         deleted_version_pks = list(deleted_version_pks)
     # Return the deleted versions!
     return self._get_versions(db).filter(pk__in=deleted_version_pks).order_by("-pk")
Ejemplo n.º 3
0
    def __init__(self, field, field_name, obj, version1, version2, manager,
                 is_reversed):
        self.field = field
        self.field_name = field_name
        self.obj = obj

        model = self.obj.__class__
        self.has_int_pk = has_int_pk(model)
        self.adapter = manager.get_adapter(model)  # VersionAdapter instance

        # is a related field (ForeignKey, ManyToManyField etc.)
        self.is_related = getattr(self.field, 'rel', None) is not None
        self.is_reversed = is_reversed
        if not self.is_related:
            self.follow = None
        elif self.field_name in self.adapter.follow:
            self.follow = True
        else:
            self.follow = False

        self.compare_obj1 = CompareObject(field, field_name, obj, version1,
                                          self.has_int_pk, self.adapter)
        self.compare_obj2 = CompareObject(field, field_name, obj, version2,
                                          self.has_int_pk, self.adapter)

        self.value1 = self.compare_obj1.value
        self.value2 = self.compare_obj2.value
Ejemplo n.º 4
0
 def get_queryset(self, request):
     """Returns the annotated queryset."""
     content_type = ContentType.objects.get_for_model(self.model)
     pk = self.model._meta.pk
     if has_int_pk(self.model):
         version_table_field = "object_id_int"
     else:
         version_table_field = "object_id"
     return super(VersionMetaAdmin, self).get_queryset(request).extra(
         select={
             "date_modified": """
                 SELECT MAX(%(revision_table)s.date_created)
                 FROM %(version_table)s
                 JOIN %(revision_table)s ON %(revision_table)s.id = %(version_table)s.revision_id 
                 WHERE %(version_table)s.content_type_id = %%s AND %(version_table)s.%(version_table_field)s = %(table)s.%(pk)s 
             """ % {
                 "revision_table":
                 connection.ops.quote_name(Revision._meta.db_table),
                 "version_table":
                 connection.ops.quote_name(Version._meta.db_table),
                 "table":
                 connection.ops.quote_name(self.model._meta.db_table),
                 "pk":
                 connection.ops.quote_name(pk.db_column or pk.attname),
                 "version_table_field":
                 connection.ops.quote_name(version_table_field),
             }
         },
         select_params=(content_type.id, ),
     )
Ejemplo n.º 5
0
 def get_deleted(self, model_class):
     """
     Returns all the deleted versions for the given model class.
     
     The results are returned with the most recent versions first.
     """
     content_type = ContentType.objects.get_for_model(model_class)
     live_pk_queryset = model_class._default_manager.all().values_list(
         "pk", flat=True)
     versioned_objs = self._get_versions().filter(
         content_type=content_type, )
     if has_int_pk(model_class):
         # We can do this as a fast, in-database join.
         deleted_version_pks = versioned_objs.exclude(
             object_id_int__in=live_pk_queryset).values_list(
                 "object_id_int")
     else:
         # This join has to be done as two separate queries.
         deleted_version_pks = versioned_objs.exclude(object_id__in=list(
             live_pk_queryset.iterator())).values_list("object_id")
     deleted_version_pks = deleted_version_pks.exclude(
         type=VERSION_DELETE, ).annotate(latest_pk=Max("pk")).values_list(
             "latest_pk", flat=True)
     return self._get_versions().filter(
         pk__in=deleted_version_pks).order_by("-pk")
Ejemplo n.º 6
0
 def get_queryset(self, request):
     """Returns the annotated queryset."""
     content_type = ContentType.objects.get_for_model(self.model)
     pk = self.model._meta.pk
     if has_int_pk(self.model):
         version_table_field = "object_id_int"
     else:
         version_table_field = "object_id"
     return super(VersionMetaAdmin, self).get_queryset(request).extra(
         select = {
             "date_modified": """
                 SELECT MAX(%(revision_table)s.date_created)
                 FROM %(version_table)s
                 JOIN %(revision_table)s ON %(revision_table)s.id = %(version_table)s.revision_id 
                 WHERE %(version_table)s.content_type_id = %%s AND %(version_table)s.%(version_table_field)s = %(table)s.%(pk)s 
             """ % {
                 "revision_table": connection.ops.quote_name(Revision._meta.db_table),
                 "version_table": connection.ops.quote_name(Version._meta.db_table),
                 "table": connection.ops.quote_name(self.model._meta.db_table),
                 "pk": connection.ops.quote_name(pk.db_column or pk.attname),
                 "version_table_field": connection.ops.quote_name(version_table_field),
             }
         },
         select_params = (content_type.id,),
     )
Ejemplo n.º 7
0
 def get_deleted(self, model_class, db=None, model_db=None):
     """
     Returns all the deleted versions for the given model class.
     
     The results are returned with the most recent versions first.
     """
     db = db or DEFAULT_DB_ALIAS
     model_db = model_db or db
     content_type = ContentType.objects.db_manager(db).get_for_model(model_class)
     live_pk_queryset = model_class._default_manager.db_manager(model_db).all().values_list("pk", flat=True)
     versioned_objs = self._get_versions(db).filter(
         content_type = content_type,
     )
     if has_int_pk(model_class):
         # If the model and version data are in different databases, decouple the queries.
         if model_db != db:
             live_pk_queryset = list(live_pk_queryset.iterator())
         # We can do this as a fast, in-database join.
         deleted_version_pks = versioned_objs.exclude(
             object_id_int__in = live_pk_queryset
         ).values_list("object_id_int")
     else:
         # This join has to be done as two separate queries.
         deleted_version_pks = versioned_objs.exclude(
             object_id__in = list(live_pk_queryset.iterator())
         ).values_list("object_id")
     deleted_version_pks = deleted_version_pks.exclude(
         type = VERSION_DELETE,
     ).annotate(
         latest_pk = Max("pk")
     ).values_list("latest_pk", flat=True)
     return self._get_versions(db).filter(pk__in=deleted_version_pks).order_by("-pk")
    def create_initial_revisions(self,
                                 app,
                                 model_class,
                                 comment,
                                 batch_size,
                                 verbosity=2,
                                 **kwargs):
        """Creates the set of initial revisions for the given model."""
        # Import the relevant admin module.
        try:
            import_module("%s.admin" % app.__name__.rsplit(".", 1)[0])
        except ImportError:
            pass
        # Check all models for empty revisions.
        if default_revision_manager.is_registered(model_class):
            created_count = 0
            content_type = ContentType.objects.get_for_model(model_class)
            versioned_pk_queryset = Version.objects.filter(
                content_type=content_type).all()
            live_objs = model_class._default_manager.all()
            if has_int_pk(model_class):
                # We can do this as a fast database join!
                live_objs = live_objs.exclude(
                    pk__in=versioned_pk_queryset.values_list("object_id_int",
                                                             flat=True))
            else:
                # This join has to be done as two separate queries.
                live_objs = live_objs.exclude(pk__in=list(
                    versioned_pk_queryset.values_list("object_id",
                                                      flat=True).iterator()))
            # Save all the versions.
            ids = list(
                live_objs.values_list(model_class._meta.pk.name, flat=True))
            total = len(ids)
            for i in xrange(0, total, batch_size):
                chunked_ids = ids[i:i + batch_size]
                objects = live_objs.in_bulk(chunked_ids)
                for id, obj in objects.iteritems():
                    try:
                        default_revision_manager.save_revision((obj, ),
                                                               comment=comment)
                    except:
                        print "ERROR: Could not save initial version for %s %s." % (
                            model_class.__name__, obj.pk)
                        raise
                    created_count += 1
                reset_queries()
                if verbosity >= 2:
                    print u"Created %s of %s." % (created_count, total)

            # Print out a message, if feeling verbose.
            if verbosity >= 2:
                print u"Created %s initial revision(s) for model %s." % (
                    created_count, smart_unicode(
                        model_class._meta.verbose_name))
        else:
            if verbosity >= 2:
                print u"Model %s is not registered." % (smart_unicode(
                    model_class._meta.verbose_name))
 def forwards(self, orm):
     "Write your forwards methods here."
     for version in orm.Version.objects.all().iterator():
         try:
             content_type = ContentType.objects.get_for_id(version.content_type_id)
         except AttributeError:
             version.delete()  # This version refers to a content type that doesn't exist any more.
             continue
         model = content_type.model_class()
         if has_int_pk(model):
             version.object_id_int = int(version.object_id)
             version.save()
 def delete_for_object_reference(self, model, object_id, db=None):
     db = db or DEFAULT_DB_ALIAS
     content_type = ContentType.objects.db_manager(db).get_for_model(model)
     versions = self._get_versions(db).filter(
         content_type = content_type,
     ).select_related("revision")
     if has_int_pk(model):
         # We can do this as a fast, indexed lookup.
         object_id_int = int(object_id)
         versions.filter(object_id_int=object_id_int).delete()
     else:
         # We can't do this using an index. Never mind.
         object_id = force_text(object_id)
         versions.filter(object_id=object_id).delete()
     return 0
    def create_initial_revisions(self, app, model_class, comment, batch_size, verbosity=2, database=None, **kwargs):
        """Creates the set of initial revisions for the given model."""
        # Import the relevant admin module.
        try:
            import_module("%s.admin" % app.__name__.rsplit(".", 1)[0])
        except ImportError:
            pass
        # Check all models for empty revisions.
        if default_revision_manager.is_registered(model_class):
            if verbosity >= 2:
                print("Creating initial revision(s) for model %s ..."  % (force_text(model_class._meta.verbose_name)))
            created_count = 0
            content_type = ContentType.objects.db_manager(database).get_for_model(model_class)
            versioned_pk_queryset = Version.objects.using(database).filter(content_type=content_type).all()
            live_objs = model_class._default_manager.using(database).all()
            if has_int_pk(model_class):
                # We can do this as a fast database join!
                live_objs = live_objs.exclude(
                    pk__in = versioned_pk_queryset.values_list("object_id_int", flat=True)
                )
            else:
                # This join has to be done as two separate queries.
                live_objs = live_objs.exclude(
                    pk__in = list(versioned_pk_queryset.values_list("object_id", flat=True).iterator())
                )
            # Save all the versions.
            ids = list(live_objs.values_list(model_class._meta.pk.name, flat=True))
            total = len(ids)
            for i in range(0, total, batch_size):
                chunked_ids = ids[i:i+batch_size]
                objects = live_objs.in_bulk(chunked_ids)
                for id, obj in objects.items():
                    try:
                        default_revision_manager.save_revision((obj,), comment=comment, db=database)
                    except:
                        print("ERROR: Could not save initial version for %s %s." % (model_class.__name__, obj.pk))
                        raise
                    created_count += 1
                reset_queries()
                if verbosity >= 2:
                    print("Created %s of %s." % (created_count, total))

            # Print out a message, if feeling verbose.
            if verbosity >= 2:
                print("Created %s initial revision(s) for model %s." % (created_count, force_text(model_class._meta.verbose_name)))
        else:
            if verbosity >= 2:
                print("Model %s is not registered."  % (force_text(model_class._meta.verbose_name)))
Ejemplo n.º 12
0
 def get_version_data(self, obj, db=None):
     """Creates the version data to be saved to the version model."""
     object_id = force_text(obj.pk)
     content_type = ContentType.objects.db_manager(db).get_for_model(obj)
     if has_int_pk(obj.__class__):
         object_id_int = int(obj.pk)
     else:
         object_id_int = None
     return {
         "object_id": object_id,
         "object_id_int": object_id_int,
         "content_type": content_type,
         "format": self.get_serialization_format(),
         "serialized_data": self.get_serialized_data(obj),
         "object_repr": force_text(obj),
     }
 def get_version_data(self, obj, db=None):
     """Creates the version data to be saved to the version model."""
     object_id = force_text(obj.pk)
     content_type = ContentType.objects.db_manager(db).get_for_model(obj)
     if has_int_pk(obj.__class__):
         object_id_int = int(obj.pk)
     else:
         object_id_int = None
     return {
         "object_id": object_id,
         "object_id_int": object_id_int,
         "content_type": content_type,
         "format": self.get_serialization_format(),
         "serialized_data": self.get_serialized_data(obj),
         "object_repr": force_text(obj),
     }
Ejemplo n.º 14
0
 def get_version_data(self, obj, type_flag):
     """Creates the version data to be saved to the version model."""
     object_id = unicode(obj.pk)
     content_type = ContentType.objects.get_for_model(obj)
     if has_int_pk(obj.__class__):
         object_id_int = int(obj.pk)
     else:
         object_id_int = None
     return {
         "object_id": object_id,
         "object_id_int": object_id_int,
         "content_type": content_type,
         "format": self.get_serialization_format(),
         "serialized_data": self.get_serialized_data(obj),
         "object_repr": unicode(obj),
         "type": type_flag,
     }
Ejemplo n.º 15
0
 def get_version_data(self, obj, type_flag):
     """Creates the version data to be saved to the version model."""
     object_id = unicode(obj.pk)
     content_type = ContentType.objects.get_for_model(obj)
     if has_int_pk(obj.__class__):
         object_id_int = int(obj.pk)
     else:
         object_id_int = None
     return {
         "object_id": object_id,
         "object_id_int": object_id_int,
         "content_type": content_type,
         "format": self.get_serialization_format(),
         "serialized_data": self.get_serialized_data(obj),
         "object_repr": unicode(obj),
         "type": type_flag
     }
Ejemplo n.º 16
0
 def get_version_data(self, obj, type_flag, db=None):
     """Creates the version data to be saved to the version model."""
     object_id = unicode(obj.pk)
     db = db or django.db.DEFAULT_DB_ALIAS
     content_type = ContentType.objects.db_manager(db).get_for_model(obj)
     if has_int_pk(obj.__class__):
         object_id_int = int(obj.pk)
     else:
         object_id_int = None
     return {
         "object_id": object_id,
         "object_id_int": object_id_int,
         "content_type": content_type,
         "format": self.get_serialization_format(),
         "serialized_data": self.get_serialized_data(obj),
         "object_repr": unicode(obj),
         "type": type_flag
     }
Ejemplo n.º 17
0
 def get_for_object_reference(self, model, object_id):
     """
     Returns all versions for the given object reference.
     
     The results are returned with the most recent versions first.
     """
     content_type = ContentType.objects.get_for_model(model)
     versions = self._get_versions().filter(content_type=content_type).select_related("revision")
     if has_int_pk(model):
         # We can do this as a fast, indexed lookup.
         object_id_int = int(object_id)
         versions = versions.filter(object_id_int=object_id_int)
     else:
         # We can't do this using an index. Never mind.
         object_id = unicode(object_id)
         versions = versions.filter(object_id=object_id)
     versions = versions.order_by("-pk")
     return versions
Ejemplo n.º 18
0
    def get_for_object_reference(self, model, object_id, db=None):
        """
        Returns all versions for the given object reference.

        The results are returned with the most recent versions first.
        """
        content_type = ContentType.objects.db_manager(db).get_for_model(model)
        versions = self._get_versions(db).filter(
            content_type=content_type, ).select_related("revision")
        if has_int_pk(model):
            # We can do this as a fast, indexed lookup.
            object_id_int = int(object_id)
            versions = versions.filter(object_id_int=object_id_int)
        else:
            # We can't do this using an index. Never mind.
            object_id = force_text(object_id)
            versions = versions.filter(object_id=object_id)
        versions = versions.order_by("-pk")
        return versions
Ejemplo n.º 19
0
    def get_for_object_reference(self, model, object_id, db=None):
        """
        Returns all versions for the given object reference.

        The results are returned with the most recent versions first.
        """
        content_type = ContentType.objects.db_manager(db).get_for_model(model)
        versions = self._get_versions(db).filter(
            content_type = content_type,
        ).select_related('revision')
        if has_int_pk(model):
            # We can do this as a fast, indexed lookup.
            object_id_int = int(object_id)
            versions = versions.filter(object_id_int=object_id_int)
        else:
            # We can't do this using an index. Never mind.
            object_id = force_text(object_id)
            versions = versions.filter(object_id=object_id)
        versions = versions.order_by('-pk')
        return versions
Ejemplo n.º 20
0
 def get_for_object_reference(self, model, object_id, db=None):
     """
     Returns all versions for the given object reference.
     
     The results are returned with the most recent versions first.
     """
     if isinstance(model, (str, unicode)):
         model = get_model(*model.split("."))
     db = db or DEFAULT_DB_ALIAS
     content_type = ContentType.objects.db_manager(db).get_for_model(model)
     versions = self._get_versions(db).filter(content_type=content_type,).select_related("revision")
     if has_int_pk(model):
         # We can do this as a fast, indexed lookup.
         object_id_int = int(object_id)
         versions = versions.filter(object_id_int=object_id_int)
     else:
         # We can't do this using an index. Never mind.
         object_id = force_text(object_id)
         versions = versions.filter(object_id=object_id)
     versions = versions.order_by("-pk")
     return versions
Ejemplo n.º 21
0
 def get_version_data(self, obj, type_flag, db=None):
     """Creates the version data to be saved to the version model."""
     object_id = force_text(obj.pk)
     db = db or DEFAULT_DB_ALIAS
     content_type = ContentType.objects.db_manager(db).get_for_model(obj)
     if has_int_pk(obj.__class__):
         object_id_int = int(obj.pk)
     else:
         object_id_int = None
     object_repr = None
     try:
         object_repr = unicode(obj)
     except:
         object_repr = u"Error occurred while unicoding object"
     return {
         "object_id": object_id,
         "object_id_int": object_id_int,
         "content_type": content_type,
         "format": self.get_serialization_format(),
         "serialized_data": self.get_serialized_data(obj),
         "object_repr": object_repr,
         "type": type_flag
     }
Ejemplo n.º 22
0
 def create_initial_revisions(self, app, model_class, comment, verbosity=2, **kwargs):
     """Creates the set of initial revisions for the given model."""
     # Import the relevant admin module.
     try:
         import_module("%s.admin" % app.__name__.rsplit(".", 1)[0])
     except ImportError:
         pass
     # Check all models for empty revisions.
     if default_revision_manager.is_registered(model_class):
         created_count = 0
         content_type = ContentType.objects.get_for_model(model_class)
         versioned_pk_queryset = Version.objects.filter(content_type=content_type).all()
         live_objs = model_class._default_manager.all()
         if has_int_pk(model_class):
             # We can do this as a fast database join!
             live_objs = live_objs.exclude(
                 pk__in = versioned_pk_queryset.values_list("object_id_int", flat=True)
             )
         else:
             # This join has to be done as two separate queries.
             live_objs = live_objs.exclude(
                 pk__in = list(versioned_pk_queryset.values_list("object_id", flat=True).iterator())
             )
         # Save all the versions.
         for obj in live_objs:
             try:
                 default_revision_manager.save_revision((obj,), comment=comment)
             except:
                 print "ERROR: Could not save initial version for %s %s." % (model_class.__name__, obj.pk)
                 raise
             created_count += 1
         # Print out a message, if feeling verbose.
         if verbosity >= 2:
             print u"Created %s initial revision(s) for model %s." % (created_count, smart_unicode(model_class._meta.verbose_name))
     else:
         if verbosity >= 2:
             print u"Model %s is not registered."  % (smart_unicode(model_class._meta.verbose_name))
Ejemplo n.º 23
0
    def __init__(self, field, field_name, obj, version1, version2, manager):
        self.field = field
        self.field_name = field_name
        self.obj = obj

        model = self.obj.__class__
        self.has_int_pk = has_int_pk(model)
        self.adapter = manager.get_adapter(model) # VersionAdapter instance

        # is a related field (ForeignKey, ManyToManyField etc.)
        self.is_related = self.field.rel is not None
        
        if not self.is_related:
            self.follow = None
        elif self.field_name in self.adapter.follow:
            self.follow = True
        else:
            self.follow = False          

        self.compare_obj1 = CompareObject(field, field_name, obj, version1, self.has_int_pk, self.adapter)
        self.compare_obj2 = CompareObject(field, field_name, obj, version2, self.has_int_pk, self.adapter)

        self.value1 = self.compare_obj1.value
        self.value2 = self.compare_obj2.value
Ejemplo n.º 24
0
 def __init__(self, *args, **kwargs):
     """Initializes the VersionMetaAdmin."""
     super(VersionMetaAdmin, self).__init__(*args, **kwargs)
     # Check that the model has an int pk.
     if not has_int_pk(self.model):
         raise ImproperlyConfigured("Cannot use VersionMetaAdmin unless the model has an integer primary key.")