From 3296298d21f32173780c753f7f8b6c2e7bd9d3e7 Mon Sep 17 00:00:00 2001 From: Saria Hajjar Date: Tue, 25 Feb 2020 14:48:11 +0000 Subject: [PATCH] Fixes #4227: Omit internal fields from the change log data --- docs/release-notes/version-2.7.md | 5 +++-- netbox/dcim/models/__init__.py | 13 +++++++++++-- netbox/utilities/utils.py | 16 ++++++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/release-notes/version-2.7.md b/docs/release-notes/version-2.7.md index 45990bd29..04c4fa79c 100644 --- a/docs/release-notes/version-2.7.md +++ b/docs/release-notes/version-2.7.md @@ -4,12 +4,13 @@ * [#3145](https://github.com/netbox-community/netbox/issues/3145) - Add a "decommissioning" cable status * [#4173](https://github.com/netbox-community/netbox/issues/4173) - Return graceful error message when webhook queuing fails +* [#4227](https://github.com/netbox-community/netbox/issues/4227) - Omit internal fields from the change log data ## Bug Fixes * [#4221](https://github.com/netbox-community/netbox/issues/4221) - Fix exception when deleting a device with interface connections when an interfaces webhook is defined * [#4222](https://github.com/netbox-community/netbox/issues/4222) - Escape double quotes on encapsulated values during CSV export -* [#4224](https://github.com/netbox-community/netbox/issues/4224) - Fix display of rear device image if front image is not defined +* [#4224](https://github.com/netbox-community/netbox/issues/4224) - Fix display of rear device image if front image is not defined * [#4228](https://github.com/netbox-community/netbox/issues/4228) - Improve fit of device images in rack elevations * [#4230](https://github.com/netbox-community/netbox/issues/4230) - Fix rack units filtering on elevation endpoint * [#4232](https://github.com/netbox-community/netbox/issues/4232) - Enforce consistent background striping in rack elevations @@ -29,7 +30,7 @@ NetBox, run the following management command to recalculate their naturalized va ``` python3 manage.py renaturalize dcim.Interface -``` +``` ## Enhancements diff --git a/netbox/dcim/models/__init__.py b/netbox/dcim/models/__init__.py index 93e7bea1d..821b8eeb7 100644 --- a/netbox/dcim/models/__init__.py +++ b/netbox/dcim/models/__init__.py @@ -20,10 +20,10 @@ from dcim.choices import * from dcim.constants import * from dcim.fields import ASNField from dcim.elevations import RackElevationSVG -from extras.models import ConfigContextModel, CustomFieldModel, TaggedItem +from extras.models import ConfigContextModel, CustomFieldModel, ObjectChange, TaggedItem from utilities.fields import ColorField, NaturalOrderingField from utilities.models import ChangeLoggedModel -from utilities.utils import to_meters +from utilities.utils import serialize_object, to_meters from .device_component_templates import ( ConsolePortTemplate, ConsoleServerPortTemplate, DeviceBayTemplate, FrontPortTemplate, InterfaceTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate, @@ -118,6 +118,15 @@ class Region(MPTTModel, ChangeLoggedModel): Q(region__in=self.get_descendants()) ).count() + def to_objectchange(self, action): + # Remove MPTT-internal fields + return ObjectChange( + changed_object=self, + object_repr=str(self), + action=action, + object_data=serialize_object(self, exclude=['level', 'lft', 'rght', 'tree_id']) + ) + # # Sites diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py index 6bef3093c..371a0530b 100644 --- a/netbox/utilities/utils.py +++ b/netbox/utilities/utils.py @@ -81,10 +81,12 @@ def get_subquery(model, field): return subquery -def serialize_object(obj, extra=None): +def serialize_object(obj, extra=None, exclude=None): """ Return a generic JSON representation of an object using Django's built-in serializer. (This is used for things like - change logging, not the REST API.) Optionally include a dictionary to supplement the object data. + change logging, not the REST API.) Optionally include a dictionary to supplement the object data. A list of keys + can be provided to exclude them from the returned dictionary. Private fields (prefaced with an underscore) are + implicitly excluded. """ json_str = serialize('json', [obj]) data = json.loads(json_str)[0]['fields'] @@ -103,6 +105,16 @@ def serialize_object(obj, extra=None): if extra is not None: data.update(extra) + # Copy keys to list to avoid 'dictionary changed size during iteration' exception + for key in list(data): + # Private fields shouldn't be logged in the object change + if isinstance(key, str) and key.startswith('_'): + data.pop(key) + + # Explicitly excluded keys + if isinstance(exclude, (list, tuple)) and key in exclude: + data.pop(key) + return data