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.

@@ -158,26 +158,35 @@ class HookQuerySetMixin:
158
158
  else:
159
159
  setattr(obj, field, value)
160
160
 
161
- # Check if we're in a bulk operation context to prevent double hook execution
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
- # If we're in a bulk operation context, skip hooks to prevent double execution
166
+ # Only skip hooks if explicitly bypassed (not for recursion prevention)
167
167
  if current_bypass_hooks:
168
- logger.debug("update: skipping hooks (bulk context)")
168
+ logger.debug("update: hooks explicitly bypassed")
169
169
  ctx = HookContext(model_cls, bypass_hooks=True)
170
170
  else:
171
- logger.debug("update: running hooks (standalone)")
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
- # Run validation hooks first
174
- engine.run(model_cls, VALIDATE_UPDATE, instances, originals, ctx=ctx)
175
- # Then run BEFORE_UPDATE hooks
176
- engine.run(model_cls, BEFORE_UPDATE, instances, originals, ctx=ctx)
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 = self._detect_modified_fields(instances, originals)
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
- if has_subquery and instances:
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
- # Run AFTER_UPDATE hooks for standalone updates or subquery operations
399
- # For subquery operations, we need to run hooks even if we're in a bulk context
400
- # because subqueries bypass the normal object-level update flow
401
- should_run_hooks = (
402
- not current_bypass_hooks
403
- or has_subquery # Always run hooks for subquery operations
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
- if should_run_hooks:
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: skipping AFTER_UPDATE (bulk context)")
423
+ logger.debug("update: AFTER_UPDATE explicitly bypassed")
411
424
 
412
425
  return update_count
413
426
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.243
3
+ Version: 0.1.245
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
@@ -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=73l5YZXea1vhQr2H3JagVwYPAtuw9FVzp3Qb2khEwIY,50215
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.243.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
15
- django_bulk_hooks-0.1.243.dist-info/METADATA,sha256=29LtTjeGKvX-piAZAVOJqthlW_9IzTMTLI6L0GBh-4A,9049
16
- django_bulk_hooks-0.1.243.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
17
- django_bulk_hooks-0.1.243.dist-info/RECORD,,
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,,