Maintain a list of modified fields on each instance of a change-logged model #6757

Open
opened 2025-12-29 19:45:06 +01:00 by adam · 3 comments
Owner

Originally created by @jeremystretch on GitHub (Aug 2, 2022).

NetBox version

v3.3-beta1

Feature type

New functionality

Proposed functionality

Implement a mechanism for tracking which attributes (if any) of a pre-existing instance have been modified from their original values. For example, when retrieving a site object from the database and then modifying the instance's name, automatically flag the name field as having been modified. This can be done by defining a list of fields named _changed_fields on the instance.

Use case

Being able to infer which fields of an instance have been modified unlocks some very interesting potential.

  1. It obviates the need to manually call snapshot() on each instance in a view: This can be handled automatically on the first change to a field.
  2. It enables responsive updates of denormalized (cached) database fields on other models (see #9788).

Database changes

No response

External dependencies

No response

Originally created by @jeremystretch on GitHub (Aug 2, 2022). ### NetBox version v3.3-beta1 ### Feature type New functionality ### Proposed functionality Implement a mechanism for tracking which attributes (if any) of a pre-existing instance have been modified from their original values. For example, when retrieving a site object from the database and then modifying the instance's name, automatically flag the `name` field as having been modified. This can be done by defining a list of fields named `_changed_fields` on the instance. ### Use case Being able to infer which fields of an instance have been modified unlocks some very interesting potential. 1. It obviates the need to manually call `snapshot()` on each instance in a view: This can be handled automatically on the first change to a field. 2. It enables responsive updates of denormalized (cached) database fields on other models (see #9788). ### Database changes _No response_ ### External dependencies _No response_
adam added the type: featurenetboxstatus: backlogcomplexity: high labels 2025-12-29 19:45:06 +01:00
Author
Owner

@github-actions[bot] commented on GitHub (Oct 2, 2022):

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide.

@github-actions[bot] commented on GitHub (Oct 2, 2022): This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).
Author
Owner

@jeremystretch commented on GitHub (Jul 25, 2023):

A variation of the approach described above has been implemented as part of #6347 (cached device & VM component counts) for NetBox v3.6. We can likely iterate on that work to achieve a more general purpose solution.

@jeremystretch commented on GitHub (Jul 25, 2023): A variation of the approach described above has been implemented as part of #6347 (cached device & VM component counts) for NetBox v3.6. We can likely iterate on that work to achieve a more general purpose solution.
Author
Owner

@peteeckel commented on GitHub (Jun 3, 2024):

Incidentally I needed something just like the functionality described just yesterday. The solution I found most useful for my purposes is this:

from netbox.models import NetBoxModel


class ObjectModificationMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if not hasattr(self.__class__, "check_fields"):
            self.__class__.check_fields = (
                {field.name for field in self._meta.fields}
                - {field.name for field in NetBoxModel._meta.fields}
                - {"id"}
            )

    @property
    def changed_fields(self):
        if self.pk is None:
            return None

        saved = self.__class__.objects.get(pk=self.pk)

        return {
            field
            for field in self.check_fields
            if getattr(self, field) != getattr(saved, field)
        }

Maybe it's useful as a starting point. The main advantage is that this works for any model without changes, and just initializes the class attribute check_fields when called for a model for the first time.

This implementation returns a set instead of a list, but that's just because it made more sense in my use case.

@peteeckel commented on GitHub (Jun 3, 2024): Incidentally I needed something just like the functionality described just yesterday. The solution I found most useful for my purposes is this: ``` from netbox.models import NetBoxModel class ObjectModificationMixin: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not hasattr(self.__class__, "check_fields"): self.__class__.check_fields = ( {field.name for field in self._meta.fields} - {field.name for field in NetBoxModel._meta.fields} - {"id"} ) @property def changed_fields(self): if self.pk is None: return None saved = self.__class__.objects.get(pk=self.pk) return { field for field in self.check_fields if getattr(self, field) != getattr(saved, field) } ``` Maybe it's useful as a starting point. The main advantage is that this works for any model without changes, and just initializes the class attribute `check_fields` when called for a model for the first time. This implementation returns a set instead of a list, but that's just because it made more sense in my use case.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#6757