tracker.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. # Copyright © 2023 Ingram Micro Inc. All rights reserved.
  2. from model_utils import FieldTracker
  3. from model_utils.tracker import FieldInstanceTracker
  4. from dj_cqrs.constants import ALL_BASIC_FIELDS, FIELDS_TRACKER_FIELD_NAME
  5. from dj_cqrs.utils import get_json_valid_value
  6. class _CQRSTrackerInstance(FieldInstanceTracker):
  7. def __init__(self, instance, fields, field_map):
  8. super().__init__(instance, fields, field_map)
  9. self._attr_to_field_map = {
  10. f.attname: f.name for f in instance._meta.concrete_fields if f.is_relation
  11. }
  12. def changed(self):
  13. changed_fields = super().changed()
  14. return {self._attr_to_field_map.get(k, k): v for k, v in changed_fields.items()}
  15. def changed_initial(self):
  16. return {field: None for field in self.fields if self.get_field_value(field) is not None}
  17. def get_field_value(self, field):
  18. value = super().get_field_value(field)
  19. return get_json_valid_value(value)
  20. class CQRSTracker(FieldTracker):
  21. tracker_class = _CQRSTrackerInstance
  22. @classmethod
  23. def add_to_model(cls, model_cls):
  24. """
  25. Add the CQRSTracker to a model.
  26. :param model_cls: the model class to which add the CQRSTracker.
  27. :type model_cls: django.db.models.Model
  28. """
  29. opts = model_cls._meta
  30. fields_to_track = []
  31. declared = model_cls.CQRS_TRACKED_FIELDS
  32. for field in opts.concrete_fields:
  33. if declared == ALL_BASIC_FIELDS or field.name in declared:
  34. fields_to_track.append(
  35. field.attname if field.is_relation else field.name,
  36. )
  37. tracker = cls(fields=fields_to_track)
  38. model_cls.add_to_class(FIELDS_TRACKER_FIELD_NAME, tracker)
  39. tracker.finalize_class(model_cls)