django-bulk-hooks 0.1.71__py3-none-any.whl → 0.1.73__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 +10 -0
- django_bulk_hooks/manager.py +37 -11
- django_bulk_hooks/queryset.py +16 -3
- {django_bulk_hooks-0.1.71.dist-info → django_bulk_hooks-0.1.73.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.1.71.dist-info → django_bulk_hooks-0.1.73.dist-info}/RECORD +7 -7
- {django_bulk_hooks-0.1.71.dist-info → django_bulk_hooks-0.1.73.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.1.71.dist-info → django_bulk_hooks-0.1.73.dist-info}/WHEEL +0 -0
django_bulk_hooks/context.py
CHANGED
|
@@ -10,6 +10,16 @@ def get_hook_queue():
|
|
|
10
10
|
return _hook_context.queue
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
def is_in_bulk_operation():
|
|
14
|
+
"""Check if we're currently in a bulk operation to prevent recursion."""
|
|
15
|
+
return getattr(_hook_context, "in_bulk_operation", False)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def set_bulk_operation_flag(value):
|
|
19
|
+
"""Set the bulk operation flag to prevent recursion."""
|
|
20
|
+
_hook_context.in_bulk_operation = value
|
|
21
|
+
|
|
22
|
+
|
|
13
23
|
class HookContext:
|
|
14
24
|
def __init__(self, model_cls, metadata=None):
|
|
15
25
|
self.model_cls = model_cls
|
django_bulk_hooks/manager.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from django.db import models, transaction
|
|
2
|
+
|
|
2
3
|
from django_bulk_hooks import engine
|
|
3
4
|
from django_bulk_hooks.constants import (
|
|
4
5
|
AFTER_CREATE,
|
|
@@ -8,10 +9,10 @@ from django_bulk_hooks.constants import (
|
|
|
8
9
|
BEFORE_DELETE,
|
|
9
10
|
BEFORE_UPDATE,
|
|
10
11
|
VALIDATE_CREATE,
|
|
11
|
-
VALIDATE_UPDATE,
|
|
12
12
|
VALIDATE_DELETE,
|
|
13
|
+
VALIDATE_UPDATE,
|
|
13
14
|
)
|
|
14
|
-
from django_bulk_hooks.context import HookContext
|
|
15
|
+
from django_bulk_hooks.context import HookContext, is_in_bulk_operation, set_bulk_operation_flag
|
|
15
16
|
from django_bulk_hooks.queryset import HookQuerySet
|
|
16
17
|
|
|
17
18
|
|
|
@@ -22,7 +23,9 @@ class BulkHookManager(models.Manager):
|
|
|
22
23
|
return HookQuerySet(self.model, using=self._db)
|
|
23
24
|
|
|
24
25
|
@transaction.atomic
|
|
25
|
-
def bulk_update(
|
|
26
|
+
def bulk_update(
|
|
27
|
+
self, objs, fields, bypass_hooks=False, bypass_validation=False, **kwargs
|
|
28
|
+
):
|
|
26
29
|
if not objs:
|
|
27
30
|
return []
|
|
28
31
|
|
|
@@ -34,13 +37,27 @@ class BulkHookManager(models.Manager):
|
|
|
34
37
|
)
|
|
35
38
|
|
|
36
39
|
if not bypass_hooks:
|
|
37
|
-
|
|
40
|
+
# Check if we're already in a hook context (recursive call)
|
|
41
|
+
# If so, refetch the current database state like Salesforce does
|
|
42
|
+
import threading
|
|
43
|
+
|
|
44
|
+
if hasattr(threading.current_thread(), "_hook_context"):
|
|
45
|
+
# We're in a recursive call - refetch current DB state
|
|
46
|
+
originals = list(
|
|
47
|
+
model_cls.objects.filter(pk__in=[obj.pk for obj in objs])
|
|
48
|
+
)
|
|
49
|
+
else:
|
|
50
|
+
# First call - use the passed originals
|
|
51
|
+
originals = list(
|
|
52
|
+
model_cls.objects.filter(pk__in=[obj.pk for obj in objs])
|
|
53
|
+
)
|
|
54
|
+
|
|
38
55
|
ctx = HookContext(model_cls)
|
|
39
|
-
|
|
56
|
+
|
|
40
57
|
# Run validation hooks first
|
|
41
58
|
if not bypass_validation:
|
|
42
59
|
engine.run(model_cls, VALIDATE_UPDATE, objs, originals, ctx=ctx)
|
|
43
|
-
|
|
60
|
+
|
|
44
61
|
# Then run business logic hooks
|
|
45
62
|
engine.run(model_cls, BEFORE_UPDATE, objs, originals, ctx=ctx)
|
|
46
63
|
|
|
@@ -118,11 +135,11 @@ class BulkHookManager(models.Manager):
|
|
|
118
135
|
|
|
119
136
|
if not bypass_hooks:
|
|
120
137
|
ctx = HookContext(model_cls)
|
|
121
|
-
|
|
138
|
+
|
|
122
139
|
# Run validation hooks first
|
|
123
140
|
if not bypass_validation:
|
|
124
141
|
engine.run(model_cls, VALIDATE_CREATE, objs, ctx=ctx)
|
|
125
|
-
|
|
142
|
+
|
|
126
143
|
# Then run business logic hooks
|
|
127
144
|
engine.run(model_cls, BEFORE_CREATE, objs, ctx=ctx)
|
|
128
145
|
|
|
@@ -136,7 +153,9 @@ class BulkHookManager(models.Manager):
|
|
|
136
153
|
return result
|
|
137
154
|
|
|
138
155
|
@transaction.atomic
|
|
139
|
-
def bulk_delete(
|
|
156
|
+
def bulk_delete(
|
|
157
|
+
self, objs, batch_size=None, bypass_hooks=False, bypass_validation=False
|
|
158
|
+
):
|
|
140
159
|
if not objs:
|
|
141
160
|
return []
|
|
142
161
|
|
|
@@ -153,12 +172,19 @@ class BulkHookManager(models.Manager):
|
|
|
153
172
|
# Run validation hooks first
|
|
154
173
|
if not bypass_validation:
|
|
155
174
|
engine.run(model_cls, VALIDATE_DELETE, objs, ctx=ctx)
|
|
156
|
-
|
|
175
|
+
|
|
157
176
|
# Then run business logic hooks
|
|
158
177
|
engine.run(model_cls, BEFORE_DELETE, objs, ctx=ctx)
|
|
159
178
|
|
|
160
179
|
pks = [obj.pk for obj in objs if obj.pk is not None]
|
|
161
|
-
|
|
180
|
+
|
|
181
|
+
# Set flag to prevent recursion during the actual deletion
|
|
182
|
+
set_bulk_operation_flag(True)
|
|
183
|
+
try:
|
|
184
|
+
# Use the custom manager - hooks won't fire again due to the flag
|
|
185
|
+
model_cls.objects.filter(pk__in=pks).delete()
|
|
186
|
+
finally:
|
|
187
|
+
set_bulk_operation_flag(False)
|
|
162
188
|
|
|
163
189
|
if not bypass_hooks:
|
|
164
190
|
engine.run(model_cls, AFTER_DELETE, objs, ctx=ctx)
|
django_bulk_hooks/queryset.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from django.db import models, transaction
|
|
2
|
+
from django_bulk_hooks.context import is_in_bulk_operation
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
class HookQuerySet(models.QuerySet):
|
|
@@ -7,7 +8,13 @@ class HookQuerySet(models.QuerySet):
|
|
|
7
8
|
objs = list(self)
|
|
8
9
|
if not objs:
|
|
9
10
|
return 0
|
|
10
|
-
|
|
11
|
+
|
|
12
|
+
# If we're already in a bulk operation, use base manager to prevent recursion
|
|
13
|
+
if is_in_bulk_operation():
|
|
14
|
+
return self.model._base_manager.bulk_delete(objs)
|
|
15
|
+
else:
|
|
16
|
+
# Normal case - use custom manager to ensure hooks fire
|
|
17
|
+
return self.model.objects.bulk_delete(objs)
|
|
11
18
|
|
|
12
19
|
@transaction.atomic
|
|
13
20
|
def update(self, **kwargs):
|
|
@@ -35,8 +42,14 @@ class HookQuerySet(models.QuerySet):
|
|
|
35
42
|
engine.run(model_cls, "before_update", instances, originals, ctx=ctx)
|
|
36
43
|
|
|
37
44
|
# Use Django's built-in update logic directly
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
# Set flag to prevent recursion during the actual update
|
|
46
|
+
from django_bulk_hooks.context import set_bulk_operation_flag
|
|
47
|
+
set_bulk_operation_flag(True)
|
|
48
|
+
try:
|
|
49
|
+
queryset = self.model.objects.filter(pk__in=pks)
|
|
50
|
+
update_count = queryset.update(**kwargs)
|
|
51
|
+
finally:
|
|
52
|
+
set_bulk_operation_flag(False)
|
|
40
53
|
|
|
41
54
|
# Run AFTER_UPDATE hooks
|
|
42
55
|
engine.run(model_cls, "after_update", instances, originals, ctx=ctx)
|
|
@@ -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=4fUfw6eMDu2V4h9EFY7uy8uDcIL0v0Fk2YVSn6V1xMI,701
|
|
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
|
-
django_bulk_hooks/manager.py,sha256=
|
|
9
|
+
django_bulk_hooks/manager.py,sha256=PYPq0incwM16tULpCfbR93GrGHcPtGyj4w6s0w1HCn0,7788
|
|
10
10
|
django_bulk_hooks/models.py,sha256=7RG7GrOdHXFjGVPV4FPRZVNMIHHW-hMCi6hn9LH_hVI,3331
|
|
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=dFYBK-CEtWPTJ9zKSc6EJLaQ8oHxR49nnzQiEGKeyOo,1996
|
|
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.73.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
15
|
+
django_bulk_hooks-0.1.73.dist-info/METADATA,sha256=NFnctdgus6n6e96VVcR1IeNh8DDVa1WzI6XyDr2iHd4,5930
|
|
16
|
+
django_bulk_hooks-0.1.73.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
17
|
+
django_bulk_hooks-0.1.73.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|