django-bulk-hooks 0.1.85__tar.gz → 0.1.86__tar.gz
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-0.1.85 → django_bulk_hooks-0.1.86}/PKG-INFO +1 -1
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/engine.py +26 -8
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/models.py +16 -37
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/pyproject.toml +1 -1
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/LICENSE +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/README.md +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/queryset.py +0 -0
- {django_bulk_hooks-0.1.85 → django_bulk_hooks-0.1.86}/django_bulk_hooks/registry.py +0 -0
|
@@ -8,7 +8,12 @@ from django_bulk_hooks.conditions import safe_get_related_object, safe_get_relat
|
|
|
8
8
|
logger = logging.getLogger(__name__)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
# Cache for hook handlers to avoid creating them repeatedly
|
|
12
|
+
_handler_cache = {}
|
|
13
|
+
|
|
11
14
|
def run(model_cls, event, new_instances, original_instances=None, ctx=None):
|
|
15
|
+
# Get hooks from cache or fetch them
|
|
16
|
+
cache_key = (model_cls, event)
|
|
12
17
|
hooks = get_hooks(model_cls, event)
|
|
13
18
|
|
|
14
19
|
if not hooks:
|
|
@@ -32,19 +37,32 @@ def run(model_cls, event, new_instances, original_instances=None, ctx=None):
|
|
|
32
37
|
logger.error("Unexpected error during validation for %s: %s", instance, e)
|
|
33
38
|
raise
|
|
34
39
|
|
|
40
|
+
# Pre-create None list for originals if needed
|
|
41
|
+
if original_instances is None:
|
|
42
|
+
original_instances = [None] * len(new_instances)
|
|
43
|
+
|
|
44
|
+
# Process all hooks
|
|
35
45
|
for handler_cls, method_name, condition, priority in hooks:
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
# Get or create handler instance from cache
|
|
47
|
+
handler_key = (handler_cls, method_name)
|
|
48
|
+
if handler_key not in _handler_cache:
|
|
49
|
+
handler_instance = handler_cls()
|
|
50
|
+
func = getattr(handler_instance, method_name)
|
|
51
|
+
_handler_cache[handler_key] = (handler_instance, func)
|
|
52
|
+
else:
|
|
53
|
+
handler_instance, func = _handler_cache[handler_key]
|
|
54
|
+
|
|
55
|
+
# If no condition, process all instances at once
|
|
56
|
+
if not condition:
|
|
57
|
+
func(new_records=new_instances, old_records=original_instances if any(original_instances) else None)
|
|
58
|
+
continue
|
|
38
59
|
|
|
60
|
+
# For conditional hooks, filter instances first
|
|
39
61
|
to_process_new = []
|
|
40
62
|
to_process_old = []
|
|
41
63
|
|
|
42
|
-
for new, original in zip(
|
|
43
|
-
|
|
44
|
-
original_instances or [None] * len(new_instances),
|
|
45
|
-
strict=True,
|
|
46
|
-
):
|
|
47
|
-
if not condition or condition.check(new, original):
|
|
64
|
+
for new, original in zip(new_instances, original_instances, strict=True):
|
|
65
|
+
if condition.check(new, original):
|
|
48
66
|
to_process_new.append(new)
|
|
49
67
|
to_process_old.append(original)
|
|
50
68
|
|
|
@@ -91,40 +91,24 @@ class HookModelMixin(models.Model):
|
|
|
91
91
|
is_create = self.pk is None
|
|
92
92
|
ctx = HookContext(self.__class__)
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
# Use a single context manager for all hooks
|
|
95
|
+
with patch_foreign_key_behavior():
|
|
96
|
+
if is_create:
|
|
97
|
+
# For create operations
|
|
97
98
|
run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
|
|
98
|
-
|
|
99
|
-
# Then let Django save
|
|
100
|
-
super().save(*args, **kwargs)
|
|
101
|
-
|
|
102
|
-
# Then run AFTER hooks
|
|
103
|
-
with patch_foreign_key_behavior():
|
|
99
|
+
super().save(*args, **kwargs)
|
|
104
100
|
run(self.__class__, AFTER_CREATE, [self], ctx=ctx)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# Run BEFORE hooks first
|
|
111
|
-
with patch_foreign_key_behavior():
|
|
101
|
+
else:
|
|
102
|
+
# For update operations
|
|
103
|
+
try:
|
|
104
|
+
old_instance = self.__class__.objects.get(pk=self.pk)
|
|
112
105
|
run(self.__class__, BEFORE_UPDATE, [self], [old_instance], ctx=ctx)
|
|
113
|
-
|
|
114
|
-
# Then let Django save
|
|
115
|
-
super().save(*args, **kwargs)
|
|
116
|
-
|
|
117
|
-
# Then run AFTER hooks
|
|
118
|
-
with patch_foreign_key_behavior():
|
|
106
|
+
super().save(*args, **kwargs)
|
|
119
107
|
run(self.__class__, AFTER_UPDATE, [self], [old_instance], ctx=ctx)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
with patch_foreign_key_behavior():
|
|
108
|
+
except self.__class__.DoesNotExist:
|
|
109
|
+
# If the old instance doesn't exist, treat as create
|
|
123
110
|
run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
|
|
124
|
-
|
|
125
|
-
super().save(*args, **kwargs)
|
|
126
|
-
|
|
127
|
-
with patch_foreign_key_behavior():
|
|
111
|
+
super().save(*args, **kwargs)
|
|
128
112
|
run(self.__class__, AFTER_CREATE, [self], ctx=ctx)
|
|
129
113
|
|
|
130
114
|
return self
|
|
@@ -132,16 +116,11 @@ class HookModelMixin(models.Model):
|
|
|
132
116
|
def delete(self, *args, **kwargs):
|
|
133
117
|
ctx = HookContext(self.__class__)
|
|
134
118
|
|
|
135
|
-
#
|
|
119
|
+
# Use a single context manager for all hooks
|
|
136
120
|
with patch_foreign_key_behavior():
|
|
137
121
|
run(self.__class__, VALIDATE_DELETE, [self], ctx=ctx)
|
|
138
|
-
|
|
139
|
-
# Then run business logic hooks
|
|
140
|
-
with patch_foreign_key_behavior():
|
|
141
122
|
run(self.__class__, BEFORE_DELETE, [self], ctx=ctx)
|
|
142
|
-
|
|
143
|
-
result = super().delete(*args, **kwargs)
|
|
144
|
-
|
|
145
|
-
with patch_foreign_key_behavior():
|
|
123
|
+
result = super().delete(*args, **kwargs)
|
|
146
124
|
run(self.__class__, AFTER_DELETE, [self], ctx=ctx)
|
|
125
|
+
|
|
147
126
|
return result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|