django-activity-audit 1.3.0.dev7__tar.gz → 1.3.0.dev8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/PKG-INFO +1 -1
  2. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/signals.py +17 -32
  3. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/pyproject.toml +1 -1
  4. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/.gitignore +0 -0
  5. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/.pre-commit-config.yaml +0 -0
  6. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/LICENSE +0 -0
  7. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/MANIFEST.in +0 -0
  8. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/README.md +0 -0
  9. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/README.rst +0 -0
  10. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/__init__.py +0 -0
  11. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/apps.py +0 -0
  12. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/constants.py +0 -0
  13. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/formatters.py +0 -0
  14. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/handlers.py +0 -0
  15. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/logger_levels.py +0 -0
  16. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/middleware.py +0 -0
  17. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/protocols.py +0 -0
  18. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/settings.py +0 -0
  19. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/activity_audit/utils.py +0 -0
  20. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/hatch +0 -0
  21. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/pytest.ini +0 -0
  22. {django_activity_audit-1.3.0.dev7 → django_activity_audit-1.3.0.dev8}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-activity-audit
3
- Version: 1.3.0.dev7
3
+ Version: 1.3.0.dev8
4
4
  Summary: A Django package for easy CRUD operation logging and container logs
5
5
  Project-URL: Homepage, https://github.com/shree256/django-activity-audit
6
6
  Project-URL: Repository, https://github.com/shree256/django-activity-audit
@@ -79,25 +79,7 @@ def get_calling_model() -> Optional[str]:
79
79
  return None
80
80
 
81
81
 
82
- class ModelSignalMixin:
83
- """Mixin to add signal handling capabilities to models."""
84
-
85
- def __init__(self, *args: Any, **kwargs: Any) -> None:
86
- super().__init__(*args, **kwargs)
87
- self._original_m2m = self._get_m2m_state()
88
-
89
- def _get_m2m_state(self) -> dict:
90
- try:
91
- """Get the current state of M2M fields."""
92
- return {
93
- field.name: set(
94
- getattr(self, field.name).all().values_list("id", flat=True)
95
- )
96
- for field in self._meta.many_to_many
97
- }
98
- except Exception as e:
99
- logger.error(f"Error getting M2M state: {e}")
100
- return {}
82
+ _patched_models: set = set()
101
83
 
102
84
 
103
85
  def push_log(
@@ -131,12 +113,15 @@ def push_log(
131
113
  logger.error(f"Failed to prepare audit log: {e}")
132
114
 
133
115
 
116
+ def instance_to_dict(instance: models.Model) -> dict:
117
+ return model_to_dict(instance, fields=[f.name for f in instance._meta.fields])
118
+
119
+
134
120
  def patch_model_event(model_class: type[models.Model]) -> None:
135
121
  """Monkey patch a model to add signal handling capabilities."""
136
122
 
137
- if not issubclass(model_class, ModelSignalMixin):
138
- # Add the mixin to the model's base classes
139
- model_class.__bases__ = (ModelSignalMixin,) + model_class.__bases__
123
+ if model_class not in _patched_models:
124
+ _patched_models.add(model_class)
140
125
 
141
126
  # Store the original methods
142
127
  original_save = model_class.save
@@ -154,7 +139,7 @@ def patch_model_event(model_class: type[models.Model]) -> None:
154
139
  # Log the event
155
140
  event_type = EVENT_TYPES[0] if is_new else EVENT_TYPES[1]
156
141
 
157
- instance_repr = model_to_dict(self)
142
+ instance_repr = instance_to_dict(self)
158
143
 
159
144
  push_log(
160
145
  f"{event_type} event by {model_class.__name__} (id: {self.pk})",
@@ -179,7 +164,7 @@ def patch_model_event(model_class: type[models.Model]) -> None:
179
164
 
180
165
  # For new instances, we might not have a pk yet, so use a placeholder
181
166
  instance_id = str(instance.pk) if instance.pk else "pending"
182
- instance_repr = model_to_dict(instance)
167
+ instance_repr = instance_to_dict(instance)
183
168
 
184
169
  push_log(
185
170
  f"{event_type} event by {model_class.__name__} (id: {instance_id})",
@@ -208,7 +193,7 @@ def patch_model_event(model_class: type[models.Model]) -> None:
208
193
  # Log only if this is the calling model
209
194
  if calling_model == model_class.__name__:
210
195
  first_obj = created_objs[0]
211
- instance_repr = model_to_dict(first_obj)
196
+ instance_repr = instance_to_dict(first_obj)
212
197
 
213
198
  push_log(
214
199
  f"{EVENT_TYPES[3]} event by {model_class.__name__} (id: {first_obj.pk})",
@@ -231,17 +216,17 @@ def patch_model_event(model_class: type[models.Model]) -> None:
231
216
  return original_bulk_update(self, objs, fields, batch_size)
232
217
 
233
218
  # Call the original bulk_update method
234
- original_bulk_update(self, objs, fields, batch_size)
219
+ bulk_update = original_bulk_update(self, objs, fields, batch_size)
235
220
 
236
221
  # Get the calling model
237
222
  calling_model = get_calling_model()
238
223
  if not calling_model:
239
- return original_bulk_update(self, objs, fields, batch_size)
224
+ return bulk_update
240
225
 
241
226
  # Log only if this is the calling model
242
227
  if calling_model == model_class.__name__:
243
228
  first_obj = objs[0]
244
- instance_repr = model_to_dict(first_obj)
229
+ instance_repr = instance_to_dict(first_obj)
245
230
 
246
231
  push_log(
247
232
  f"{EVENT_TYPES[4]} event by {model_class.__name__}",
@@ -268,7 +253,7 @@ def patch_model_event(model_class: type[models.Model]) -> None:
268
253
  if not should_audit(instance):
269
254
  return
270
255
 
271
- instance_repr = model_to_dict(instance)
256
+ instance_repr = instance_to_dict(instance)
272
257
 
273
258
  push_log(
274
259
  f"{EVENT_TYPES[8]} event by {model_class.__name__} (id: {instance.pk})",
@@ -283,7 +268,7 @@ def patch_model_event(model_class: type[models.Model]) -> None:
283
268
  def handle_delete(
284
269
  sender: type[models.Model], instance: models.Model, **kwargs: Any
285
270
  ) -> None:
286
- instance_repr = model_to_dict(instance)
271
+ instance_repr = instance_to_dict(instance)
287
272
 
288
273
  push_log(
289
274
  f"{EVENT_TYPES[2]} event by {model_class.__name__} (id: {instance.pk})",
@@ -308,7 +293,7 @@ def patch_model_event(model_class: type[models.Model]) -> None:
308
293
  return
309
294
 
310
295
  field_name = kwargs.get("model", sender).__name__.lower()
311
- instance_repr = model_to_dict(instance)
296
+ instance_repr = instance_to_dict(instance)
312
297
 
313
298
  push_log(
314
299
  f"M2M {action} event by {model_class.__name__} (id: {instance.pk})",
@@ -330,7 +315,7 @@ def setup_model_signals() -> None:
330
315
  if not should_audit(model):
331
316
  continue
332
317
 
333
- if not issubclass(model, ModelSignalMixin):
318
+ if model not in _patched_models:
334
319
  patch_model_event(model)
335
320
 
336
321
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "django-activity-audit"
3
- version = "1.3.0.dev7"
3
+ version = "1.3.0.dev8"
4
4
  description = "A Django package for easy CRUD operation logging and container logs"
5
5
  authors = [
6
6
  { name = "Shreeshan", email = "shreeshan256@gmail.com" }