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