django-bulk-hooks 0.1.246__py3-none-any.whl → 0.1.247__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 +36 -7
- {django_bulk_hooks-0.1.246.dist-info → django_bulk_hooks-0.1.247.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.1.246.dist-info → django_bulk_hooks-0.1.247.dist-info}/RECORD +5 -5
- {django_bulk_hooks-0.1.246.dist-info → django_bulk_hooks-0.1.247.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.1.246.dist-info → django_bulk_hooks-0.1.247.dist-info}/WHEEL +0 -0
django_bulk_hooks/queryset.py
CHANGED
|
@@ -172,14 +172,17 @@ class HookQuerySetMixin:
|
|
|
172
172
|
logger.debug("update: running hooks with Salesforce-style behavior")
|
|
173
173
|
ctx = HookContext(model_cls, bypass_hooks=False)
|
|
174
174
|
|
|
175
|
-
# Run hooks before database update for both Subquery and non-Subquery cases
|
|
176
175
|
# Run validation hooks first
|
|
177
176
|
engine.run(model_cls, VALIDATE_UPDATE, instances, originals, ctx=ctx)
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
|
|
178
|
+
# For Subquery updates, skip BEFORE_UPDATE hooks here - they'll run after refresh
|
|
179
|
+
if not has_subquery:
|
|
180
|
+
# Then run BEFORE_UPDATE hooks for non-Subquery updates
|
|
181
|
+
engine.run(model_cls, BEFORE_UPDATE, instances, originals, ctx=ctx)
|
|
180
182
|
|
|
181
183
|
# Persist any additional field mutations made by BEFORE_UPDATE hooks.
|
|
182
184
|
# Build CASE statements per modified field not already present in kwargs.
|
|
185
|
+
# Note: For Subquery updates, this will be empty since hooks haven't run yet
|
|
183
186
|
modified_fields = self._detect_modified_fields(instances, originals)
|
|
184
187
|
extra_fields = [f for f in modified_fields if f not in kwargs]
|
|
185
188
|
if extra_fields:
|
|
@@ -378,7 +381,7 @@ class HookQuerySetMixin:
|
|
|
378
381
|
raise
|
|
379
382
|
|
|
380
383
|
# If we used Subquery objects, refresh the instances to get computed values
|
|
381
|
-
#
|
|
384
|
+
# and run BEFORE_UPDATE hooks so HasChanged conditions work correctly
|
|
382
385
|
if has_subquery and instances and not current_bypass_hooks:
|
|
383
386
|
logger.debug(
|
|
384
387
|
"Refreshing instances with Subquery computed values before running hooks"
|
|
@@ -389,20 +392,46 @@ class HookQuerySetMixin:
|
|
|
389
392
|
obj.pk: obj for obj in model_cls._base_manager.filter(pk__in=pks)
|
|
390
393
|
}
|
|
391
394
|
|
|
392
|
-
# Bulk update all instances in memory
|
|
395
|
+
# Bulk update all instances in memory and save pre-hook state
|
|
396
|
+
pre_hook_state = {}
|
|
393
397
|
for instance in instances:
|
|
394
398
|
if instance.pk in refreshed_instances:
|
|
395
399
|
refreshed_instance = refreshed_instances[instance.pk]
|
|
396
|
-
#
|
|
400
|
+
# Save current state before modifying for hook comparison
|
|
401
|
+
pre_hook_values = {}
|
|
397
402
|
for field in model_cls._meta.fields:
|
|
398
403
|
if field.name != "id":
|
|
404
|
+
pre_hook_values[field.name] = getattr(refreshed_instance, field.name)
|
|
399
405
|
setattr(
|
|
400
406
|
instance,
|
|
401
407
|
field.name,
|
|
402
408
|
getattr(refreshed_instance, field.name),
|
|
403
409
|
)
|
|
410
|
+
pre_hook_state[instance.pk] = pre_hook_values
|
|
411
|
+
|
|
412
|
+
# Now run BEFORE_UPDATE hooks with refreshed instances so conditions work
|
|
413
|
+
logger.debug("Running BEFORE_UPDATE hooks after Subquery refresh")
|
|
414
|
+
engine.run(model_cls, BEFORE_UPDATE, instances, originals, ctx=ctx)
|
|
404
415
|
|
|
405
|
-
|
|
416
|
+
# Check if hooks modified any fields and persist them with bulk_update
|
|
417
|
+
hook_modified_fields = set()
|
|
418
|
+
for instance in instances:
|
|
419
|
+
if instance.pk in pre_hook_state:
|
|
420
|
+
pre_hook_values = pre_hook_state[instance.pk]
|
|
421
|
+
for field_name, pre_hook_value in pre_hook_values.items():
|
|
422
|
+
current_value = getattr(instance, field_name)
|
|
423
|
+
if current_value != pre_hook_value:
|
|
424
|
+
hook_modified_fields.add(field_name)
|
|
425
|
+
|
|
426
|
+
hook_modified_fields = list(hook_modified_fields)
|
|
427
|
+
if hook_modified_fields:
|
|
428
|
+
logger.debug(
|
|
429
|
+
f"Running bulk_update for hook-modified fields: {hook_modified_fields}"
|
|
430
|
+
)
|
|
431
|
+
# Use bulk_update to persist hook modifications, bypassing hooks to avoid recursion
|
|
432
|
+
model_cls.objects.bulk_update(
|
|
433
|
+
instances, hook_modified_fields, bypass_hooks=True
|
|
434
|
+
)
|
|
406
435
|
|
|
407
436
|
# Salesforce-style: Always run AFTER_UPDATE hooks unless explicitly bypassed
|
|
408
437
|
if not current_bypass_hooks:
|
|
@@ -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=CHcQzKNQvdYWnIUHqG5tkngWtiBKEvyEeJMXUpNkTzc,52108
|
|
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.247.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
15
|
+
django_bulk_hooks-0.1.247.dist-info/METADATA,sha256=yyIsZ_9DgoIzDl7y6fCvPTW2W-Asc7Dtfuo0Tlj5fcA,9049
|
|
16
|
+
django_bulk_hooks-0.1.247.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
17
|
+
django_bulk_hooks-0.1.247.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|