django-bulk-hooks 0.1.215__tar.gz → 0.1.216__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.
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/PKG-INFO +1 -1
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/context.py +12 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/queryset.py +26 -10
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/pyproject.toml +1 -1
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/LICENSE +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/README.md +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/engine.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/models.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/priority.py +0 -0
- {django_bulk_hooks-0.1.215 → django_bulk_hooks-0.1.216}/django_bulk_hooks/registry.py +0 -0
|
@@ -12,10 +12,22 @@ def get_hook_queue():
|
|
|
12
12
|
return _hook_context.queue
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
def set_bypass_hooks(bypass_hooks):
|
|
16
|
+
"""Set the current bypass_hooks state for the current thread."""
|
|
17
|
+
_hook_context.bypass_hooks = bypass_hooks
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_bypass_hooks():
|
|
21
|
+
"""Get the current bypass_hooks state for the current thread."""
|
|
22
|
+
return getattr(_hook_context, 'bypass_hooks', False)
|
|
23
|
+
|
|
24
|
+
|
|
15
25
|
class HookContext:
|
|
16
26
|
def __init__(self, model, bypass_hooks=False):
|
|
17
27
|
self.model = model
|
|
18
28
|
self.bypass_hooks = bypass_hooks
|
|
29
|
+
# Set the thread-local bypass state when creating a context
|
|
30
|
+
set_bypass_hooks(bypass_hooks)
|
|
19
31
|
|
|
20
32
|
@property
|
|
21
33
|
def is_executing(self):
|
|
@@ -72,9 +72,19 @@ class HookQuerySetMixin:
|
|
|
72
72
|
for field, value in kwargs.items():
|
|
73
73
|
setattr(obj, field, value)
|
|
74
74
|
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
# Check if we're in a bulk operation context to prevent double hook execution
|
|
76
|
+
from django_bulk_hooks.context import get_bypass_hooks
|
|
77
|
+
current_bypass_hooks = get_bypass_hooks()
|
|
78
|
+
|
|
79
|
+
# If we're in a bulk operation context, skip hooks to prevent double execution
|
|
80
|
+
if current_bypass_hooks:
|
|
81
|
+
print(f"DEBUG: update method skipping hooks due to bulk operation context")
|
|
82
|
+
ctx = HookContext(model_cls, bypass_hooks=True)
|
|
83
|
+
else:
|
|
84
|
+
print(f"DEBUG: update method running hooks (standalone update)")
|
|
85
|
+
ctx = HookContext(model_cls, bypass_hooks=False)
|
|
86
|
+
# Run BEFORE_UPDATE hooks only for standalone updates
|
|
87
|
+
engine.run(model_cls, BEFORE_UPDATE, instances, originals, ctx=ctx)
|
|
78
88
|
|
|
79
89
|
# Use Django's built-in update logic directly
|
|
80
90
|
# Call the base QuerySet implementation to avoid recursion
|
|
@@ -101,8 +111,12 @@ class HookQuerySetMixin:
|
|
|
101
111
|
getattr(refreshed_instance, field.name),
|
|
102
112
|
)
|
|
103
113
|
|
|
104
|
-
# Run AFTER_UPDATE hooks
|
|
105
|
-
|
|
114
|
+
# Run AFTER_UPDATE hooks only for standalone updates
|
|
115
|
+
if not current_bypass_hooks:
|
|
116
|
+
print(f"DEBUG: update method running AFTER_UPDATE hooks")
|
|
117
|
+
engine.run(model_cls, AFTER_UPDATE, instances, originals, ctx=ctx)
|
|
118
|
+
else:
|
|
119
|
+
print(f"DEBUG: update method skipping AFTER_UPDATE hooks due to bulk operation context")
|
|
106
120
|
|
|
107
121
|
return update_count
|
|
108
122
|
|
|
@@ -161,12 +175,13 @@ class HookQuerySetMixin:
|
|
|
161
175
|
|
|
162
176
|
# Fire hooks before DB ops
|
|
163
177
|
if not bypass_hooks:
|
|
164
|
-
ctx = HookContext(model_cls, bypass_hooks=False)
|
|
178
|
+
ctx = HookContext(model_cls, bypass_hooks=False) # Pass bypass_hooks
|
|
165
179
|
if not bypass_validation:
|
|
166
180
|
engine.run(model_cls, VALIDATE_CREATE, objs, ctx=ctx)
|
|
167
181
|
engine.run(model_cls, BEFORE_CREATE, objs, ctx=ctx)
|
|
168
182
|
else:
|
|
169
|
-
ctx = HookContext(model_cls, bypass_hooks=True)
|
|
183
|
+
ctx = HookContext(model_cls, bypass_hooks=True) # Pass bypass_hooks
|
|
184
|
+
print(f"DEBUG: Set thread-local bypass_hooks=True for nested calls in bulk_create")
|
|
170
185
|
|
|
171
186
|
# For MTI models, we need to handle them specially
|
|
172
187
|
if is_mti:
|
|
@@ -233,8 +248,7 @@ class HookQuerySetMixin:
|
|
|
233
248
|
break
|
|
234
249
|
|
|
235
250
|
if not bypass_hooks:
|
|
236
|
-
print(f"DEBUG:
|
|
237
|
-
# Load originals for hook comparison
|
|
251
|
+
print(f"DEBUG: bulk_update running hooks for {len(objs)} objects")
|
|
238
252
|
original_map = {
|
|
239
253
|
obj.pk: obj
|
|
240
254
|
for obj in model_cls._base_manager.filter(
|
|
@@ -259,8 +273,10 @@ class HookQuerySetMixin:
|
|
|
259
273
|
fields_set.update(modified_fields)
|
|
260
274
|
fields = list(fields_set)
|
|
261
275
|
else:
|
|
262
|
-
print(f"DEBUG:
|
|
276
|
+
print(f"DEBUG: bulk_update skipping hooks and setting bulk context to prevent double execution")
|
|
263
277
|
ctx = HookContext(model_cls, bypass_hooks=True)
|
|
278
|
+
print(f"DEBUG: Set thread-local bypass_hooks=True to prevent nested update() calls from running hooks")
|
|
279
|
+
originals = [None] * len(objs) # Ensure originals is defined for after_update call
|
|
264
280
|
|
|
265
281
|
# Handle auto_now fields like Django's update_or_create does
|
|
266
282
|
fields_set = set(fields)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "django-bulk-hooks"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.216"
|
|
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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|