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.
- django_bulk_hooks/engine.py +7 -0
- django_bulk_hooks/models.py +7 -0
- django_bulk_hooks/queryset.py +24 -13
- {django_bulk_hooks-0.1.207.dist-info → django_bulk_hooks-0.1.209.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.1.207.dist-info → django_bulk_hooks-0.1.209.dist-info}/RECORD +7 -7
- {django_bulk_hooks-0.1.207.dist-info → django_bulk_hooks-0.1.209.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.1.207.dist-info → django_bulk_hooks-0.1.209.dist-info}/WHEEL +0 -0
django_bulk_hooks/engine.py
CHANGED
|
@@ -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,
|
django_bulk_hooks/models.py
CHANGED
|
@@ -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
|
django_bulk_hooks/queryset.py
CHANGED
|
@@ -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
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
98
|
-
|
|
99
|
-
#
|
|
100
|
-
for
|
|
101
|
-
|
|
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
|
|
|
@@ -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=
|
|
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=
|
|
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=
|
|
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.
|
|
15
|
-
django_bulk_hooks-0.1.
|
|
16
|
-
django_bulk_hooks-0.1.
|
|
17
|
-
django_bulk_hooks-0.1.
|
|
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,,
|
|
File without changes
|
|
File without changes
|