django-bulk-hooks 0.1.207__py3-none-any.whl → 0.1.209__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.

@@ -20,6 +20,10 @@ def run(model_cls, event, new_records, old_records=None, ctx=None):
20
20
  if not hooks:
21
21
  return
22
22
 
23
+ print(
24
+ f"DEBUG: engine.run called for {model_cls.__name__}.{event} with {len(new_records)} records"
25
+ )
26
+
23
27
  # For BEFORE_* events, run model.clean() first for validation
24
28
  if event.startswith("before_"):
25
29
  for instance in new_records:
@@ -47,6 +51,9 @@ def run(model_cls, event, new_records, old_records=None, ctx=None):
47
51
  to_process_old.append(original)
48
52
 
49
53
  if to_process_new:
54
+ print(
55
+ f"DEBUG: Executing hook {handler_cls.__name__}.{method_name} for {len(to_process_new)} records"
56
+ )
50
57
  try:
51
58
  func(
52
59
  new_records=to_process_new,
@@ -56,11 +56,15 @@ class HookModelMixin(models.Model):
56
56
  def save(self, *args, bypass_hooks=False, **kwargs):
57
57
  # If bypass_hooks is True, use base manager to avoid triggering hooks
58
58
  if bypass_hooks:
59
+ print(
60
+ f"DEBUG: save() called with bypass_hooks=True for {self.__class__.__name__} pk={self.pk}"
61
+ )
59
62
  return self._base_manager.save(self, *args, **kwargs)
60
63
 
61
64
  is_create = self.pk is None
62
65
 
63
66
  if is_create:
67
+ print(f"DEBUG: save() creating new {self.__class__.__name__} instance")
64
68
  # For create operations, we don't have old records
65
69
  ctx = HookContext(self.__class__)
66
70
  run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
@@ -69,6 +73,9 @@ class HookModelMixin(models.Model):
69
73
 
70
74
  run(self.__class__, AFTER_CREATE, [self], ctx=ctx)
71
75
  else:
76
+ print(
77
+ f"DEBUG: save() updating existing {self.__class__.__name__} instance pk={self.pk}"
78
+ )
72
79
  # For update operations, we need to get the old record
73
80
  try:
74
81
  # Use _base_manager to avoid triggering hooks recursively
@@ -82,23 +82,24 @@ class HookQuerySetMixin:
82
82
 
83
83
  # If we used Subquery objects, refresh the instances to get computed values
84
84
  if has_subquery and instances:
85
- # Single bulk query to get all updated values
86
- # Use values() to get only the fields we need for maximum performance
87
- field_names = [f.name for f in model_cls._meta.fields if f.name != "id"]
88
- refreshed_data = {
89
- obj["pk"]: obj
90
- for obj in model_cls._base_manager.filter(pk__in=pks).values(
91
- "pk", *field_names
92
- )
85
+ # Simple refresh of model fields without fetching related objects
86
+ # Subquery updates only affect the model's own fields, not relationships
87
+ refreshed_instances = {
88
+ obj.pk: obj for obj in model_cls._base_manager.filter(pk__in=pks)
93
89
  }
94
90
 
95
91
  # Bulk update all instances in memory
96
92
  for instance in instances:
97
- if instance.pk in refreshed_data:
98
- data = refreshed_data[instance.pk]
99
- # Bulk copy all field values except primary key
100
- for field_name in field_names:
101
- setattr(instance, field_name, data[field_name])
93
+ if instance.pk in refreshed_instances:
94
+ refreshed_instance = refreshed_instances[instance.pk]
95
+ # Update all fields except primary key
96
+ for field in model_cls._meta.fields:
97
+ if field.name != "id":
98
+ setattr(
99
+ instance,
100
+ field.name,
101
+ getattr(refreshed_instance, field.name),
102
+ )
102
103
 
103
104
  # Run AFTER_UPDATE hooks
104
105
  engine.run(model_cls, AFTER_UPDATE, instances, originals, ctx=ctx)
@@ -226,6 +227,7 @@ class HookQuerySetMixin:
226
227
  break
227
228
 
228
229
  if not bypass_hooks:
230
+ print(f"DEBUG: bypass_hooks=False, running hooks for {len(objs)} objects")
229
231
  # Load originals for hook comparison
230
232
  original_map = {
231
233
  obj.pk: obj
@@ -243,6 +245,8 @@ class HookQuerySetMixin:
243
245
 
244
246
  # Then run business logic hooks
245
247
  engine.run(model_cls, BEFORE_UPDATE, objs, originals, ctx=ctx)
248
+ else:
249
+ print(f"DEBUG: bypass_hooks=True, skipping hooks for {len(objs)} objects")
246
250
 
247
251
  # Detect modified fields during hooks
248
252
  modified_fields = self._detect_modified_fields(objs, originals)
@@ -277,7 +281,14 @@ class HookQuerySetMixin:
277
281
  result = super().bulk_update(objs, fields, **django_kwargs)
278
282
 
279
283
  if not bypass_hooks:
284
+ print(
285
+ f"DEBUG: bypass_hooks=False, running AFTER_UPDATE hooks for {len(objs)} objects"
286
+ )
280
287
  engine.run(model_cls, AFTER_UPDATE, objs, originals, ctx=ctx)
288
+ else:
289
+ print(
290
+ f"DEBUG: bypass_hooks=True, skipping AFTER_UPDATE hooks for {len(objs)} objects"
291
+ )
281
292
 
282
293
  return result
283
294
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.207
3
+ Version: 0.1.209
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
@@ -3,15 +3,15 @@ django_bulk_hooks/conditions.py,sha256=mTvlLcttixbXRkTSNZU5VewkPUavbXRuD2BkJbVWM
3
3
  django_bulk_hooks/constants.py,sha256=3x1H1fSUUNo0DZONN7GUVDuySZctTR-jtByBHmAIX5w,303
4
4
  django_bulk_hooks/context.py,sha256=4IPuOX8TBAYBEMzN0RNHWgE6Giy2ZnR5uRXfd1cpIwk,1051
5
5
  django_bulk_hooks/decorators.py,sha256=WD7Jn7QAvY8F4wOsYlIpjoM9-FdHXSKB7hH9ot-lkYQ,4896
6
- django_bulk_hooks/engine.py,sha256=nA5PU9msk_Ju5Gf_sTd7GqPscuTxEW5itCDAoSScYGI,1645
6
+ django_bulk_hooks/engine.py,sha256=cIgykVNU7IeNjCNmlSqgqFRUvym-rQDJ4mBte6vWyRI,1916
7
7
  django_bulk_hooks/enums.py,sha256=Zo8_tJzuzZ2IKfVc7gZ-0tWPT8q1QhqZbAyoh9ZVJbs,381
8
8
  django_bulk_hooks/handler.py,sha256=xZt8iNdYF-ACz-MnKMY0co6scWINU5V5wC1lyDn844k,4854
9
9
  django_bulk_hooks/manager.py,sha256=nfWiwU5-yAoxdnQsUMohxtyCpkV0MBv6X3wmipr9eQY,3697
10
- django_bulk_hooks/models.py,sha256=7fnx5xd4HWXfLVlFhhiRzR92JRWFEuxgk6aSWLEsyJg,3996
10
+ django_bulk_hooks/models.py,sha256=TA2dBIA1nJBiYt6joefWkpFIQZWysF9kZlkBYvEe59c,4358
11
11
  django_bulk_hooks/priority.py,sha256=HG_2D35nga68lBCZmSXTcplXrjFoRgZFRDOy4ROKonY,376
12
- django_bulk_hooks/queryset.py,sha256=YMw8Za_1aqLkCmTqhYKnznq95IVlie3Wx9NBDND7KcM,31387
12
+ django_bulk_hooks/queryset.py,sha256=MnyNHRorpuq5JL8vHBakzCNBgqyWLYsaOrv9DtrP5nk,31941
13
13
  django_bulk_hooks/registry.py,sha256=-mQBizJ06nz_tajZBinViKx_uP2Tbc1tIpTEMv7lwKA,705
14
- django_bulk_hooks-0.1.207.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
15
- django_bulk_hooks-0.1.207.dist-info/METADATA,sha256=6XzEu4cdHtO1kVPzw-vuUmoFjbEUaVrTdEEKAFqEP60,9049
16
- django_bulk_hooks-0.1.207.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
17
- django_bulk_hooks-0.1.207.dist-info/RECORD,,
14
+ django_bulk_hooks-0.1.209.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
15
+ django_bulk_hooks-0.1.209.dist-info/METADATA,sha256=QVsx3CnCzMXTg_dt071vPf5LOxse3j9fCJ3_WzXZxm8,9049
16
+ django_bulk_hooks-0.1.209.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
17
+ django_bulk_hooks-0.1.209.dist-info/RECORD,,