django-bulk-hooks 0.1.243__py3-none-any.whl → 0.1.245__py3-none-any.whl
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/queryset.py +32 -19
- {django_bulk_hooks-0.1.243.dist-info → django_bulk_hooks-0.1.245.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.1.243.dist-info → django_bulk_hooks-0.1.245.dist-info}/RECORD +5 -5
- {django_bulk_hooks-0.1.243.dist-info → django_bulk_hooks-0.1.245.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.1.243.dist-info → django_bulk_hooks-0.1.245.dist-info}/WHEEL +0 -0
django_bulk_hooks/queryset.py
CHANGED
|
@@ -158,26 +158,35 @@ class HookQuerySetMixin:
|
|
|
158
158
|
else:
|
|
159
159
|
setattr(obj, field, value)
|
|
160
160
|
|
|
161
|
-
#
|
|
161
|
+
# Salesforce-style trigger behavior: Always run hooks, rely on Django's stack overflow protection
|
|
162
162
|
from django_bulk_hooks.context import get_bypass_hooks
|
|
163
163
|
|
|
164
164
|
current_bypass_hooks = get_bypass_hooks()
|
|
165
165
|
|
|
166
|
-
#
|
|
166
|
+
# Only skip hooks if explicitly bypassed (not for recursion prevention)
|
|
167
167
|
if current_bypass_hooks:
|
|
168
|
-
logger.debug("update:
|
|
168
|
+
logger.debug("update: hooks explicitly bypassed")
|
|
169
169
|
ctx = HookContext(model_cls, bypass_hooks=True)
|
|
170
170
|
else:
|
|
171
|
-
|
|
171
|
+
# Always run hooks - Django will handle stack overflow protection
|
|
172
|
+
logger.debug("update: running hooks with Salesforce-style behavior")
|
|
172
173
|
ctx = HookContext(model_cls, bypass_hooks=False)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
#
|
|
176
|
-
|
|
174
|
+
|
|
175
|
+
# For Subquery updates, we need to run hooks AFTER the database update and refresh
|
|
176
|
+
# For non-Subquery updates, we can run hooks before the database update as usual
|
|
177
|
+
if not has_subquery:
|
|
178
|
+
# Run validation hooks first
|
|
179
|
+
engine.run(model_cls, VALIDATE_UPDATE, instances, originals, ctx=ctx)
|
|
180
|
+
# Then run BEFORE_UPDATE hooks
|
|
181
|
+
engine.run(model_cls, BEFORE_UPDATE, instances, originals, ctx=ctx)
|
|
177
182
|
|
|
178
183
|
# Persist any additional field mutations made by BEFORE_UPDATE hooks.
|
|
179
184
|
# Build CASE statements per modified field not already present in kwargs.
|
|
180
|
-
modified_fields =
|
|
185
|
+
modified_fields = (
|
|
186
|
+
self._detect_modified_fields(instances, originals)
|
|
187
|
+
if not has_subquery
|
|
188
|
+
else set()
|
|
189
|
+
)
|
|
181
190
|
extra_fields = [f for f in modified_fields if f not in kwargs]
|
|
182
191
|
if extra_fields:
|
|
183
192
|
case_statements = {}
|
|
@@ -375,7 +384,11 @@ class HookQuerySetMixin:
|
|
|
375
384
|
raise
|
|
376
385
|
|
|
377
386
|
# If we used Subquery objects, refresh the instances to get computed values
|
|
378
|
-
|
|
387
|
+
# and then run hooks so HasChanged conditions work correctly
|
|
388
|
+
if has_subquery and instances and not current_bypass_hooks:
|
|
389
|
+
logger.debug(
|
|
390
|
+
"Refreshing instances with Subquery computed values before running hooks"
|
|
391
|
+
)
|
|
379
392
|
# Simple refresh of model fields without fetching related objects
|
|
380
393
|
# Subquery updates only affect the model's own fields, not relationships
|
|
381
394
|
refreshed_instances = {
|
|
@@ -395,19 +408,19 @@ class HookQuerySetMixin:
|
|
|
395
408
|
getattr(refreshed_instance, field.name),
|
|
396
409
|
)
|
|
397
410
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
)
|
|
411
|
+
# Now run the hooks with the refreshed instances containing computed values
|
|
412
|
+
logger.debug("Running hooks after Subquery refresh")
|
|
413
|
+
# Run validation hooks first
|
|
414
|
+
engine.run(model_cls, VALIDATE_UPDATE, instances, originals, ctx=ctx)
|
|
415
|
+
# Then run BEFORE_UPDATE hooks
|
|
416
|
+
engine.run(model_cls, BEFORE_UPDATE, instances, originals, ctx=ctx)
|
|
405
417
|
|
|
406
|
-
|
|
418
|
+
# Salesforce-style: Always run AFTER_UPDATE hooks unless explicitly bypassed
|
|
419
|
+
if not current_bypass_hooks:
|
|
407
420
|
logger.debug("update: running AFTER_UPDATE")
|
|
408
421
|
engine.run(model_cls, AFTER_UPDATE, instances, originals, ctx=ctx)
|
|
409
422
|
else:
|
|
410
|
-
logger.debug("update:
|
|
423
|
+
logger.debug("update: AFTER_UPDATE explicitly bypassed")
|
|
411
424
|
|
|
412
425
|
return update_count
|
|
413
426
|
|
|
@@ -9,9 +9,9 @@ django_bulk_hooks/handler.py,sha256=e_GACTQT-pFF-zL7POeo232MgOikUoCLcxDVInAUiBw,
|
|
|
9
9
|
django_bulk_hooks/manager.py,sha256=nfWiwU5-yAoxdnQsUMohxtyCpkV0MBv6X3wmipr9eQY,3697
|
|
10
10
|
django_bulk_hooks/models.py,sha256=WtSfc4GBOG_oOt8n37cVvid0MtFIGze9JYKSixil2y0,4370
|
|
11
11
|
django_bulk_hooks/priority.py,sha256=HG_2D35nga68lBCZmSXTcplXrjFoRgZFRDOy4ROKonY,376
|
|
12
|
-
django_bulk_hooks/queryset.py,sha256=
|
|
12
|
+
django_bulk_hooks/queryset.py,sha256=4fhRS44IZfhCyUdqqcTp7p9XUyGTLcNoViFNSPEP88I,50995
|
|
13
13
|
django_bulk_hooks/registry.py,sha256=GRUTGVQEO2sdkC9OaZ9Q3U7mM-3Ix83uTyvrlTtpatw,1317
|
|
14
|
-
django_bulk_hooks-0.1.
|
|
15
|
-
django_bulk_hooks-0.1.
|
|
16
|
-
django_bulk_hooks-0.1.
|
|
17
|
-
django_bulk_hooks-0.1.
|
|
14
|
+
django_bulk_hooks-0.1.245.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
15
|
+
django_bulk_hooks-0.1.245.dist-info/METADATA,sha256=HiXQqF3rkZYjfHL79nFgGmPOo8GKB2i6Fd39Jm_FYFI,9049
|
|
16
|
+
django_bulk_hooks-0.1.245.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
17
|
+
django_bulk_hooks-0.1.245.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|