diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index d158e6cf9..0e3cfd35f 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -40,6 +40,7 @@ * [#9075](https://github.com/netbox-community/netbox/issues/9075) - Introduce `AbortRequest` exception for cleanly interrupting object mutations * [#9092](https://github.com/netbox-community/netbox/issues/9092) - Add support for `ObjectChildrenView` generic view +* [#9228](https://github.com/netbox-community/netbox/issues/9228) - Subclasses of `ChangeLoggingMixin` can override `serialize_object()` to control JSON serialization for change logging * [#9414](https://github.com/netbox-community/netbox/issues/9414) - Add `clone()` method to NetBoxModel for copying instance attributes * [#9647](https://github.com/netbox-community/netbox/issues/9647) - Introduce `customfield_value` template tag diff --git a/netbox/extras/webhooks.py b/netbox/extras/webhooks.py index d8739cb55..334539026 100644 --- a/netbox/extras/webhooks.py +++ b/netbox/extras/webhooks.py @@ -1,6 +1,5 @@ import hashlib import hmac -from collections import defaultdict from django.contrib.contenttypes.models import ContentType from django.utils import timezone @@ -27,10 +26,18 @@ def serialize_for_webhook(instance): def get_snapshots(instance, action): - return { + snapshots = { 'prechange': getattr(instance, '_prechange_snapshot', None), - 'postchange': serialize_object(instance) if action != ObjectChangeActionChoices.ACTION_DELETE else None, + 'postchange': None, } + if action != ObjectChangeActionChoices.ACTION_DELETE: + # Use model's serialize() method if defined; fall back to serialize_object + if hasattr(instance, 'serialize_object'): + snapshots['postchange'] = instance.serialize_object() + else: + snapshots['postchange'] = serialize_object(instance) + + return snapshots def generate_signature(request_body, secret): diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 817da526b..6b2ee1f94 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -49,11 +49,19 @@ class ChangeLoggingMixin(models.Model): class Meta: abstract = True + def serialize_object(self): + """ + Return a JSON representation of the instance. Models can override this method to replace or extend the default + serialization logic provided by the `serialize_object()` utility function. + """ + return serialize_object(self) + def snapshot(self): """ - Save a snapshot of the object's current state in preparation for modification. + Save a snapshot of the object's current state in preparation for modification. The snapshot is saved as + `_prechange_snapshot` on the instance. """ - self._prechange_snapshot = serialize_object(self) + self._prechange_snapshot = self.serialize_object() def to_objectchange(self, action): """ @@ -69,7 +77,7 @@ class ChangeLoggingMixin(models.Model): if hasattr(self, '_prechange_snapshot'): objectchange.prechange_data = self._prechange_snapshot if action in (ObjectChangeActionChoices.ACTION_CREATE, ObjectChangeActionChoices.ACTION_UPDATE): - objectchange.postchange_data = serialize_object(self) + objectchange.postchange_data = self.serialize_object() return objectchange