Просмотр исходного кода

Merge pull request #4181 from hSaria/2511-change-diff

Fixes #2511: Compare object change to the previous change
Jeremy Stretch 6 лет назад
Родитель
Сommit
21473548a5

+ 1 - 0
docs/release-notes/version-2.7.md

@@ -2,6 +2,7 @@
 
 ## Enhancements
 
+* [#2511](https://github.com/netbox-community/netbox/issues/2511) - Compare object change to the previous change
 * [#3840](https://github.com/netbox-community/netbox/issues/3840) - Enhance search function when selecting VLANs for interface assignment
 * [#4170](https://github.com/netbox-community/netbox/issues/4170) - Improve color contrast in rack elevation drawings
 

+ 24 - 0
netbox/extras/views.py

@@ -12,6 +12,7 @@ from django_tables2 import RequestConfig
 
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator
+from utilities.utils import shallow_compare_dict
 from utilities.views import BulkDeleteView, BulkEditView, ObjectDeleteView, ObjectEditView, ObjectListView
 from . import filters, forms
 from .models import ConfigContext, ImageAttachment, ObjectChange, ReportResult, Tag, TaggedItem
@@ -207,8 +208,31 @@ class ObjectChangeView(PermissionRequiredMixin, View):
             orderable=False
         )
 
+        objectchanges = ObjectChange.objects.filter(
+            changed_object_type=objectchange.changed_object_type,
+            changed_object_id=objectchange.changed_object_id,
+        )
+
+        next_change = objectchanges.filter(time__gt=objectchange.time).order_by('time').first()
+        prev_change = objectchanges.filter(time__lt=objectchange.time).order_by('-time').first()
+
+        if prev_change:
+            diff_added = shallow_compare_dict(
+                prev_change.object_data,
+                objectchange.object_data,
+                exclude=['last_updated'],
+            )
+            diff_removed = {x: prev_change.object_data.get(x) for x in diff_added}
+        else:
+            # No previous change; this is the initial change that added the object
+            diff_added = diff_removed = objectchange.object_data
+
         return render(request, 'extras/objectchange.html', {
             'objectchange': objectchange,
+            'diff_added': diff_added,
+            'diff_removed': diff_removed,
+            'next_change': next_change,
+            'prev_change': prev_change,
             'related_changes_table': related_changes_table,
             'related_changes_count': related_changes.count()
         })

+ 29 - 0
netbox/templates/extras/objectchange.html

@@ -83,6 +83,35 @@
                     </tr>
                 </table>
             </div>
+            <div class="panel panel-default">
+                <div class="panel-heading">
+                    <strong>Difference</strong>
+                    <div class="btn-group btn-group-xs pull-right noprint">
+                        <a {% if prev_change %}href="{% url 'extras:objectchange' pk=prev_change.pk %}"{% else %}disabled{% endif %} class="btn btn-default">
+                            <span class="fa fa-chevron-left" aria-hidden="true"></span> Previous
+                        </a>
+                        <a {% if next_change %}href="{% url 'extras:objectchange' pk=next_change.pk %}"{% else %}disabled{% endif %} class="btn btn-default">
+                            Next <span class="fa fa-chevron-right" aria-hidden="true"></span>
+                        </a>
+                    </div>
+                </div>
+                <div class="panel-body">
+                    {% if diff_added == diff_removed %}
+                        <span class="text-muted" style="margin-left: 10px;">
+                            {% if objectchange.action == 'create' %}
+                                Object created
+                            {% elif objectchange.action == 'delete' %}
+                                Object deleted
+                            {% else %}
+                                No changes
+                            {% endif %}
+                        </span>
+                    {% else %}
+                        <pre style="background-color: #ffdce0;">{{ diff_removed|render_json }}</pre>
+                        <pre style="background-color: #cdffd8;">{{ diff_added|render_json }}</pre>
+                    {% endif %}
+                </div>
+            </div>
         </div>
         <div class="col-md-7">
             <div class="panel panel-default">

+ 16 - 0
netbox/utilities/utils.py

@@ -222,3 +222,19 @@ def querydict_to_dict(querydict):
         key: querydict.get(key) if len(value) == 1 and key != 'pk' else querydict.getlist(key)
         for key, value in querydict.lists()
     }
+
+
+def shallow_compare_dict(source_dict, destination_dict, exclude=None):
+    """
+    Return a new dictionary of the different keys. The values of `destination_dict` are returned. Only the equality of
+    the first layer of keys/values is checked. `exclude` is a list or tuple of keys to be ignored.
+    """
+    difference = {}
+
+    for key in destination_dict:
+        if source_dict.get(key) != destination_dict[key]:
+            if isinstance(exclude, (list, tuple)) and key in exclude:
+                continue
+            difference[key] = destination_dict[key]
+
+    return difference