django-bulk-hooks 0.1.147__py3-none-any.whl → 0.1.149__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/context.py +27 -3
- django_bulk_hooks/models.py +16 -4
- django_bulk_hooks/queryset.py +18 -0
- {django_bulk_hooks-0.1.147.dist-info → django_bulk_hooks-0.1.149.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.1.147.dist-info → django_bulk_hooks-0.1.149.dist-info}/RECORD +7 -7
- {django_bulk_hooks-0.1.147.dist-info → django_bulk_hooks-0.1.149.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.1.147.dist-info → django_bulk_hooks-0.1.149.dist-info}/WHEEL +0 -0
django_bulk_hooks/context.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
from collections import deque
|
|
3
|
+
from django_bulk_hooks.handler import hook_vars
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
_hook_context = threading.local()
|
|
5
7
|
|
|
@@ -11,6 +13,28 @@ def get_hook_queue():
|
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class HookContext:
|
|
14
|
-
def __init__(self,
|
|
15
|
-
self.
|
|
16
|
-
|
|
16
|
+
def __init__(self, model):
|
|
17
|
+
self.model = model
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def is_executing(self):
|
|
21
|
+
"""
|
|
22
|
+
Check if we're currently in a hook execution context.
|
|
23
|
+
Similar to Salesforce's Trigger.isExecuting.
|
|
24
|
+
Use this to prevent infinite recursion in hooks.
|
|
25
|
+
"""
|
|
26
|
+
return hasattr(hook_vars, 'event') and hook_vars.event is not None
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def current_event(self):
|
|
30
|
+
"""
|
|
31
|
+
Get the current hook event being executed.
|
|
32
|
+
"""
|
|
33
|
+
return getattr(hook_vars, 'event', None)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def execution_depth(self):
|
|
37
|
+
"""
|
|
38
|
+
Get the current execution depth to detect deep recursion.
|
|
39
|
+
"""
|
|
40
|
+
return getattr(hook_vars, 'depth', 0)
|
django_bulk_hooks/models.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from django.db import models
|
|
1
|
+
from django.db import models
|
|
2
2
|
|
|
3
3
|
from django_bulk_hooks.constants import (
|
|
4
4
|
AFTER_CREATE,
|
|
@@ -22,7 +22,7 @@ class HookModelMixin(models.Model):
|
|
|
22
22
|
class Meta:
|
|
23
23
|
abstract = True
|
|
24
24
|
|
|
25
|
-
def clean(self):
|
|
25
|
+
def clean(self, bypass_hooks=False):
|
|
26
26
|
"""
|
|
27
27
|
Override clean() to trigger validation hooks.
|
|
28
28
|
This ensures that when Django calls clean() (like in admin forms),
|
|
@@ -30,6 +30,10 @@ class HookModelMixin(models.Model):
|
|
|
30
30
|
"""
|
|
31
31
|
super().clean()
|
|
32
32
|
|
|
33
|
+
# If bypass_hooks is True, skip validation hooks
|
|
34
|
+
if bypass_hooks:
|
|
35
|
+
return
|
|
36
|
+
|
|
33
37
|
# Determine if this is a create or update operation
|
|
34
38
|
is_create = self.pk is None
|
|
35
39
|
|
|
@@ -48,7 +52,11 @@ class HookModelMixin(models.Model):
|
|
|
48
52
|
ctx = HookContext(self.__class__)
|
|
49
53
|
run(self.__class__, VALIDATE_CREATE, [self], ctx=ctx)
|
|
50
54
|
|
|
51
|
-
def save(self, *args, **kwargs):
|
|
55
|
+
def save(self, *args, bypass_hooks=False, **kwargs):
|
|
56
|
+
# If bypass_hooks is True, use base manager to avoid triggering hooks
|
|
57
|
+
if bypass_hooks:
|
|
58
|
+
return self._base_manager.save(self, *args, **kwargs)
|
|
59
|
+
|
|
52
60
|
is_create = self.pk is None
|
|
53
61
|
|
|
54
62
|
if is_create:
|
|
@@ -80,7 +88,11 @@ class HookModelMixin(models.Model):
|
|
|
80
88
|
|
|
81
89
|
return self
|
|
82
90
|
|
|
83
|
-
def delete(self, *args, **kwargs):
|
|
91
|
+
def delete(self, *args, bypass_hooks=False, **kwargs):
|
|
92
|
+
# If bypass_hooks is True, use base manager to avoid triggering hooks
|
|
93
|
+
if bypass_hooks:
|
|
94
|
+
return self._base_manager.delete(self, *args, **kwargs)
|
|
95
|
+
|
|
84
96
|
ctx = HookContext(self.__class__)
|
|
85
97
|
|
|
86
98
|
# Run validation hooks first
|
django_bulk_hooks/queryset.py
CHANGED
|
@@ -325,6 +325,10 @@ class HookQuerySet(models.QuerySet):
|
|
|
325
325
|
parent_objects_map = {}
|
|
326
326
|
|
|
327
327
|
# Step 1: Do O(n) normal inserts into parent tables to get primary keys back
|
|
328
|
+
# Get bypass_hooks from kwargs
|
|
329
|
+
bypass_hooks = kwargs.get('bypass_hooks', False)
|
|
330
|
+
bypass_validation = kwargs.get('bypass_validation', False)
|
|
331
|
+
|
|
328
332
|
for obj in batch:
|
|
329
333
|
parent_instances = {}
|
|
330
334
|
current_parent = None
|
|
@@ -332,6 +336,14 @@ class HookQuerySet(models.QuerySet):
|
|
|
332
336
|
parent_obj = self._create_parent_instance(
|
|
333
337
|
obj, model_class, current_parent
|
|
334
338
|
)
|
|
339
|
+
|
|
340
|
+
# Fire parent hooks if not bypassed
|
|
341
|
+
if not bypass_hooks:
|
|
342
|
+
ctx = HookContext(model_class)
|
|
343
|
+
if not bypass_validation:
|
|
344
|
+
engine.run(model_class, VALIDATE_CREATE, [parent_obj], ctx=ctx)
|
|
345
|
+
engine.run(model_class, BEFORE_CREATE, [parent_obj], ctx=ctx)
|
|
346
|
+
|
|
335
347
|
# Use Django's base manager to create the object and get PKs back
|
|
336
348
|
# This bypasses hooks and the MTI exception
|
|
337
349
|
field_values = {
|
|
@@ -340,10 +352,16 @@ class HookQuerySet(models.QuerySet):
|
|
|
340
352
|
if hasattr(parent_obj, field.name) and getattr(parent_obj, field.name) is not None
|
|
341
353
|
}
|
|
342
354
|
created_obj = model_class._base_manager.using(self.db).create(**field_values)
|
|
355
|
+
|
|
343
356
|
# Update the parent_obj with the created object's PK
|
|
344
357
|
parent_obj.pk = created_obj.pk
|
|
345
358
|
parent_obj._state.adding = False
|
|
346
359
|
parent_obj._state.db = self.db
|
|
360
|
+
|
|
361
|
+
# Fire AFTER_CREATE hooks for parent
|
|
362
|
+
if not bypass_hooks:
|
|
363
|
+
engine.run(model_class, AFTER_CREATE, [parent_obj], ctx=ctx)
|
|
364
|
+
|
|
347
365
|
parent_instances[model_class] = parent_obj
|
|
348
366
|
current_parent = parent_obj
|
|
349
367
|
parent_objects_map[id(obj)] = parent_instances
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
django_bulk_hooks/__init__.py,sha256=uUgpnb9AWjIAcWNpCMqBcOewSnpJjJYH6cjPbQkzoNU,140
|
|
2
2
|
django_bulk_hooks/conditions.py,sha256=mTvlLcttixbXRkTSNZU5VewkPUavbXRuD2BkJbVWMkw,6041
|
|
3
3
|
django_bulk_hooks/constants.py,sha256=3x1H1fSUUNo0DZONN7GUVDuySZctTR-jtByBHmAIX5w,303
|
|
4
|
-
django_bulk_hooks/context.py,sha256=
|
|
4
|
+
django_bulk_hooks/context.py,sha256=4IPuOX8TBAYBEMzN0RNHWgE6Giy2ZnR5uRXfd1cpIwk,1051
|
|
5
5
|
django_bulk_hooks/decorators.py,sha256=tckDcxtOzKCbgvS9QydgeIAWTFDEl-ch3_Q--ruEGdQ,4831
|
|
6
6
|
django_bulk_hooks/engine.py,sha256=3HbgV12JRYIy9IlygHPxZiHnFXj7EwzLyTuJNQeVIoI,1402
|
|
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=r54ct3S6AcqME2OsX-jPF944CEKcoSIW3qiAx_NwUaw,2801
|
|
10
|
-
django_bulk_hooks/models.py,sha256=
|
|
10
|
+
django_bulk_hooks/models.py,sha256=5PBjBoGlHwAE5b4yaZ5kDjt5UtHfQp6pDrwB2XPs2tk,3850
|
|
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=3DOzQ_UJdrngllNskeTrQyxBnFydpS6Vr7Rml9ekrPQ,21914
|
|
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.149.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
15
|
+
django_bulk_hooks-0.1.149.dist-info/METADATA,sha256=rXtNKd2ktak1gSVWdMXlbk6614_LvoZaAvY9GauSHDk,6951
|
|
16
|
+
django_bulk_hooks-0.1.149.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
17
|
+
django_bulk_hooks-0.1.149.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|