django-bulk-hooks 0.1.235__tar.gz → 0.1.236__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.

Potentially problematic release.


This version of django-bulk-hooks might be problematic. Click here for more details.

Files changed (17) hide show
  1. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/PKG-INFO +1 -1
  2. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/context.py +16 -0
  3. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/queryset.py +33 -3
  4. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/pyproject.toml +1 -1
  5. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/LICENSE +0 -0
  6. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/README.md +0 -0
  7. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/__init__.py +0 -0
  8. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/conditions.py +0 -0
  9. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/constants.py +0 -0
  10. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/decorators.py +0 -0
  11. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/engine.py +0 -0
  12. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/enums.py +0 -0
  13. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/handler.py +0 -0
  14. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/manager.py +0 -0
  15. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/models.py +0 -0
  16. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/priority.py +0 -0
  17. {django_bulk_hooks-0.1.235 → django_bulk_hooks-0.1.236}/django_bulk_hooks/registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.235
3
+ Version: 0.1.236
4
4
  Summary: Hook-style hooks for Django bulk operations like bulk_create and bulk_update.
5
5
  Home-page: https://github.com/AugendLimited/django-bulk-hooks
6
6
  License: MIT
@@ -22,6 +22,22 @@ def get_bypass_hooks():
22
22
  return getattr(_hook_context, 'bypass_hooks', False)
23
23
 
24
24
 
25
+ # Thread-local storage for passing per-object field values from bulk_update -> update
26
+ def set_bulk_update_value_map(value_map):
27
+ """Store a mapping of {pk: {field_name: value}} for the current thread.
28
+
29
+ This allows the internal update() call (triggered by Django's bulk_update)
30
+ to populate in-memory instances with the concrete values that will be
31
+ written to the database, instead of Django expression objects like Case/Cast.
32
+ """
33
+ _hook_context.bulk_update_value_map = value_map
34
+
35
+
36
+ def get_bulk_update_value_map():
37
+ """Retrieve the mapping {pk: {field_name: value}} for the current thread, if any."""
38
+ return getattr(_hook_context, 'bulk_update_value_map', None)
39
+
40
+
25
41
  class HookContext:
26
42
  def __init__(self, model, bypass_hooks=False):
27
43
  self.model = model
@@ -17,6 +17,10 @@ from django_bulk_hooks.constants import (
17
17
  VALIDATE_UPDATE,
18
18
  )
19
19
  from django_bulk_hooks.context import HookContext
20
+ from django_bulk_hooks.context import (
21
+ get_bulk_update_value_map,
22
+ set_bulk_update_value_map,
23
+ )
20
24
 
21
25
 
22
26
  class HookQuerySetMixin:
@@ -71,9 +75,15 @@ class HookQuerySetMixin:
71
75
  )
72
76
 
73
77
  # Apply field updates to instances
78
+ # If a per-object value map exists (from bulk_update), prefer it over kwargs
79
+ per_object_values = get_bulk_update_value_map()
74
80
  for obj in instances:
75
- for field, value in kwargs.items():
76
- setattr(obj, field, value)
81
+ if per_object_values and obj.pk in per_object_values:
82
+ for field, value in per_object_values[obj.pk].items():
83
+ setattr(obj, field, value)
84
+ else:
85
+ for field, value in kwargs.items():
86
+ setattr(obj, field, value)
77
87
 
78
88
  # Check if we're in a bulk operation context to prevent double hook execution
79
89
  from django_bulk_hooks.context import get_bypass_hooks
@@ -283,7 +293,27 @@ class HookQuerySetMixin:
283
293
  if k not in ["bypass_hooks", "bypass_validation"]
284
294
  }
285
295
  logger.debug("Calling Django bulk_update")
286
- result = super().bulk_update(objs, fields, **django_kwargs)
296
+ # Build a per-object concrete value map to avoid leaking expressions into hooks
297
+ value_map = {}
298
+ for obj in objs:
299
+ if obj.pk is None:
300
+ continue
301
+ field_values = {}
302
+ for field_name in fields:
303
+ # Capture raw values assigned on the object (not expressions)
304
+ field_values[field_name] = getattr(obj, field_name)
305
+ if field_values:
306
+ value_map[obj.pk] = field_values
307
+
308
+ # Make the value map available to the subsequent update() call
309
+ if value_map:
310
+ set_bulk_update_value_map(value_map)
311
+
312
+ try:
313
+ result = super().bulk_update(objs, fields, **django_kwargs)
314
+ finally:
315
+ # Always clear after the internal update() path finishes
316
+ set_bulk_update_value_map(None)
287
317
  logger.debug(f"Django bulk_update done: {result}")
288
318
 
289
319
  # Note: We don't run AFTER_UPDATE hooks here to prevent double execution
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.1.235"
3
+ version = "0.1.236"
4
4
  description = "Hook-style hooks for Django bulk operations like bulk_create and bulk_update."
5
5
  authors = ["Konrad Beck <konrad.beck@merchantcapital.co.za>"]
6
6
  readme = "README.md"