def compare(self, obj, version1, version2):
        """
        Create a generic html diff from the obj between version1 and version2:

            A diff of every changes field values.

        This method should be overwritten, to create a nice diff view
        coordinated with the model.
        """
        diff = []

        # Create a list of all normal fields and append many-to-many fields
        fields = [field for field in obj._meta.fields]
        concrete_model = obj._meta.concrete_model
        fields += concrete_model._meta.many_to_many

        # This gathers the related reverse ForeignKey fields, so we can do ManyToOne compares
        self.reverse_fields = []
        for field in obj._meta.get_fields(include_hidden=True):
            f = getattr(field, "field", None)
            if isinstance(f, models.ForeignKey) and f not in fields:
                self.reverse_fields.append(f.remote_field)

        fields += self.reverse_fields

        has_unfollowed_fields = False

        for field in fields:
            # logger.debug("%s %s %s", field, field.db_type, field.get_internal_type())
            try:
                field_name = field.name
            except BaseException:
                # is a reverse FK field
                field_name = field.field_name

            if self.compare_fields and field_name not in self.compare_fields:
                continue
            if self.compare_exclude and field_name in self.compare_exclude:
                continue

            is_reversed = field in self.reverse_fields
            obj_compare = CompareObjects(field, field_name, obj, version1, version2, is_reversed)
            # obj_compare.debug()

            is_related = obj_compare.is_related
            follow = obj_compare.follow
            if is_related and not follow:
                has_unfollowed_fields = True

            if not obj_compare.changed():
                # Skip all fields that aren't changed
                continue

            html = self._get_compare(obj_compare)
            diff.append({"field": field, "is_related": is_related, "follow": follow, "diff": html})

        return diff, has_unfollowed_fields
Esempio n. 2
0
    def compare_inline_obj(self, model_class, obj_compare):
        """
        :param model_class: ex:  BostonAphasiaSentecesWrittenDictation model class
        :param obj_compare: reversion object
        :return: html string
        """
        result = ""

        # print ('****************')
        # for attr, value in obj_compare.__dict__.iteritems():
        #     print attr, value

        fields = [field for field in model_class._meta.fields]
        for field in fields:
            field_name = field.name
            field_verbose_name = field._verbose_name or ''

            # print ('****************')
            # print (obj_compare.M2O_CHANGE_INFO)
            # for attr, value in obj_compare.__dict__.iteritems():
            #     print attr, value

            if field_name not in ('id', 'bostonAphasia'):
                if obj_compare.M2O_CHANGE_INFO and 'changed_items' in obj_compare.M2O_CHANGE_INFO and len(obj_compare.M2O_CHANGE_INFO['changed_items']) > 0:

                    c = CompareObjects(field=obj_compare.field, field_name=field_name,
                                       obj=obj_compare.obj, version1=obj_compare.M2O_CHANGE_INFO['changed_items'][0][0],
                                       version2=obj_compare.M2O_CHANGE_INFO['changed_items'][0][1], is_reversed=False)

                    # if the object value changed, print the diff html
                    if c.changed() and c.value1 != c.value2:
                        result = u'%s<p>%s - %s<br>%s</p>' % (
                        result, field_name, field_verbose_name, html_diff(('- %s' % c.value1), ('+ %s' % c.value2)))
        if result:
            return mark_safe('<pre class="highlight">%s</pre>' % result)
        else:
            return
Esempio n. 3
0
    def compare(self, obj, version1, version2):
        """
        Create a generic html diff from the obj between version1 and version2:

            A diff of every changes field values.

        This method should be overwritten, to create a nice diff view
        coordinated with the model.
        """
        diff = []

        # Create a list of all normal fields and append many-to-many fields
        fields = [field for field in obj._meta.fields]
        concrete_model = obj._meta.concrete_model
        fields += concrete_model._meta.many_to_many

        # This gathers the related reverse ForeignKey fields, so we can do ManyToOne compares
        self.reverse_fields = []
        # From: http://stackoverflow.com/questions/19512187/django-list-all-reverse-relations-of-a-model
        for field_name in obj._meta.get_all_field_names():
            f = getattr(
                obj._meta.get_field_by_name(field_name)[0],
                'field',
                None
            )
            if isinstance(f, models.ForeignKey) and f not in fields:
                self.reverse_fields.append(f.rel)
        #print(self.reverse_fields)
        fields += self.reverse_fields

        has_unfollowed_fields = False

        for field in fields:
            # logger.debug("%s %s %s", field, field.db_type, field.get_internal_type())
            try:
                field_name = field.name
            except:
                # is a reverse FK field
                field_name = field.field_name

            if self.compare_fields and field_name not in self.compare_fields:
                continue
            if self.compare_exclude and field_name in self.compare_exclude:
                continue

            is_reversed = field in self.reverse_fields
            obj_compare = CompareObjects(field, field_name, obj, version1, version2, self.revision_manager, is_reversed)
            #obj_compare.debug()

            is_related = obj_compare.is_related
            follow = obj_compare.follow
            if is_related and not follow:
                has_unfollowed_fields = True

            if not obj_compare.changed():
                # Skip all fields that aren't changed
                continue

            html = self._get_compare(obj_compare)
            diff.append({
                "field": field,
                "is_related": is_related,
                "follow": follow,
                "diff": html,
            })

        return diff, has_unfollowed_fields
Esempio n. 4
0
    def compare(self, obj, version1, version2):
        """
        Create a generic html diff from the obj between version1 and version2:

            A diff of every changes field values.

        This method should be overwritten, to create a nice diff view
        coordinated with the model.
        """
        diff = []

        # Create a list of all normal fields and append many-to-many fields
        fields = [field for field in obj._meta.fields]
        concrete_model = obj._meta.concrete_model
        properties = [name for name in dir(concrete_model)
                          if isinstance(getattr(concrete_model, name), property)]
        fields += concrete_model._meta.many_to_many

        # This gathers the related reverse ForeignKey fields, so we can do ManyToOne compares
        self.reverse_fields = []
        # From: http://stackoverflow.com/questions/19512187/django-list-all-reverse-relations-of-a-model
        for f in obj._meta.get_fields():
            if isinstance(f, models.ForeignKey) and f not in fields:
                self.reverse_fields.append(f.rel)
        #print(self.reverse_fields)
        fields += self.reverse_fields

        has_unfollowed_fields = False

        for field in fields:
            # logger.debug("%s %s %s", field, field.db_type, field.get_internal_type())
            try:
                field_name = field.name
            except:
                # is a reverse FK field
                field_name = field.field_name

            if self.compare_fields and field_name not in self.compare_fields:
                continue
            if self.compare_exclude and field_name in self.compare_exclude:
                continue

            is_reversed = field in self.reverse_fields
            obj_compare = CompareObjects(field, field_name, obj, version1, version2, self.revision_manager, is_reversed)
            #obj_compare.debug()

            is_related = obj_compare.is_related
            follow = obj_compare.follow
            if is_related and not follow:
                has_unfollowed_fields = True

            if not obj_compare.changed():
                # Skip all fields that aren't changed
                continue

            html = self._get_compare(obj_compare)
            diff.append({
                "field": field,
                "is_related": is_related,
                "follow": follow,
                "diff": html,
            })

        for prop_name in properties:
            if self.compare_props and prop_name not in self.compare_props:
                continue
            if self.compare_exclude_props and prop_name in self.compare_exclude_props:
                continue
            prop_value = getattr(obj, prop_name)
            json1 = None
            json2 = None
            try:
                with transaction.atomic():
                    version1.revision.revert(delete=True)
                    prop_value = getattr(version1.object_version.object, prop_name)
                    json1 = json.dumps(prop_value, indent=4)
                    version2.revision.revert(delete=True)
                    prop_value = getattr(version2.object_version.object, prop_name)
                    json2 = json.dumps(prop_value, indent=4)
                    raise Exception  # Raise an exception to undo the transaction and the revision.
            except Exception:
                pass
            if json1 != json2:
                html = html_diff(json1, json2)
                try:
                    prop_name = concrete_model.PropertiesMeta.verbose[prop_name]
                except:
                    prop_name = str.capitalize(prop_name)
                diff.append({
                    'name': prop_name,
                    'diff': html,
                })

        return diff, has_unfollowed_fields