Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
jeremystretch opened this issue Aug 2, 2022 · 3 comments
Labels
complexity: high Expected to require a large amont of time and effort to implement relative to other tasks netbox status: backlog Awaiting selection for work type: feature Introduction of new functionality to the application

Comments

@jeremystretch
Copy link
Member

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 Cached properties in CableTermination not updated #9788).

Database changes

No response

External dependencies

No response

@jeremystretch jeremystretch added type: feature Introduction of new functionality to the application status: under review Further discussion is needed to determine this issue's scope and/or implementation labels Aug 2, 2022
@github-actions
Copy link
Contributor

github-actions bot commented 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 github-actions bot added the pending closure Requires immediate attention to avoid being closed for inactivity label Oct 2, 2022
@jeremystretch jeremystretch added needs milestone Awaiting prioritization for inclusion with a future NetBox release and removed status: under review Further discussion is needed to determine this issue's scope and/or implementation pending closure Requires immediate attention to avoid being closed for inactivity labels Oct 20, 2022
@jeremystretch
Copy link
Member Author

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 jeremystretch added status: backlog Awaiting selection for work complexity: high Expected to require a large amont of time and effort to implement relative to other tasks labels May 21, 2024
@jeffgdotorg jeffgdotorg added this to the v4.1 milestone May 31, 2024
@peteeckel
Copy link
Contributor

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.

@jeffgdotorg jeffgdotorg removed the needs milestone Awaiting prioritization for inclusion with a future NetBox release label Jun 7, 2024
@jeremystretch jeremystretch removed their assignment Jul 24, 2024
@jeremystretch jeremystretch removed this from the v4.1 milestone Jul 24, 2024
@jeremystretch jeremystretch added the netbox label Nov 1, 2024 — with Linear
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
complexity: high Expected to require a large amont of time and effort to implement relative to other tasks netbox status: backlog Awaiting selection for work type: feature Introduction of new functionality to the application
Projects
None yet
Development

No branches or pull requests

3 participants