content: from django.db.models.query_utils import DeferredAttribute
  
  from netbox.registry import registry
  
  
  class Tracker:
      """
      An ephemeral instance employed to record which tracked fields on an instance have been modified.
      """
      def __init__(self):
          self._changed_fields = {}
  
      def __contains__(self, item):
          return item in self._changed_fields
  
      def set(self, name, value):
          """
          Mark an attribute as having been changed and record its original value.
          """
          self._changed_fields[name] = value
  
      def get(self, name):
          """
          Return the original value of a changed field. Raises KeyError if name is not found.
          """
          return self._changed_fields[name]
  
      def clear(self, *names):
          """
          Clear any fields that were recorded as having been changed.
          """
          for name in names:
              self._changed_fields.pop(name, None)
          else:
              self._changed_fields = {}
  
  
  class TrackingModelMixin:
  
      def __init__(self, *args, **kwargs):
          super().__init__(*args, **kwargs)
  
          # Mark the instance as initialized, to enable our custom __setattr__()
          self._initialized = True
  
      @property
      def tracker(self):
          """
          Return the Tracker instance for this instance, first creating it if necessary.
          """
          if not hasattr(self._state, "_tracker"):
              self._state._tracker = Tracker()
          return self._state._tracker
  
      def save(self, *args, **kwargs):
          super().save(*args, **kwargs)
  
          # Clear any tracked fields now that changes have been saved
          update_fields = kwargs.get('update_fields', [])
          self.tracker.clear(*update_fields)
  
      def __setattr__(self, name, value):
          if hasattr(self, "_initialized"):
              # Record any changes to a tracked field
              if name in registry['counter_fields'][self.__class__]:
                  if name not in self.tracker:
                      # The attribute has been created or changed
                      if name in self.__dict__:
                          old_value = getattr(self, name)
                          if value != old_value:
                              self.tracker.set(name, old_value)
                      else:
                          self.tracker.set(name, DeferredAttribute)
                  elif value == self.tracker.get(name):
                      # A previously changed attribute has been restored
                      self.tracker.clear(name)
  
          super().__setattr__(name, value)
  