django-bulk-hooks 0.1.169__tar.gz → 0.1.171__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.169 → django_bulk_hooks-0.1.171}/PKG-INFO +1 -1
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/models.py +6 -4
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/queryset.py +36 -26
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/pyproject.toml +1 -1
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/LICENSE +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/README.md +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/engine.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/priority.py +0 -0
- {django_bulk_hooks-0.1.169 → django_bulk_hooks-0.1.171}/django_bulk_hooks/registry.py +0 -0
|
@@ -44,7 +44,8 @@ class HookModelMixin(models.Model):
|
|
|
44
44
|
else:
|
|
45
45
|
# For update operations, run VALIDATE_UPDATE hooks for validation
|
|
46
46
|
try:
|
|
47
|
-
|
|
47
|
+
# Use _base_manager to avoid triggering hooks recursively
|
|
48
|
+
old_instance = self.__class__._base_manager.get(pk=self.pk)
|
|
48
49
|
ctx = HookContext(self.__class__)
|
|
49
50
|
run(self.__class__, VALIDATE_UPDATE, [self], [old_instance], ctx=ctx)
|
|
50
51
|
except self.__class__.DoesNotExist:
|
|
@@ -56,7 +57,7 @@ class HookModelMixin(models.Model):
|
|
|
56
57
|
# If bypass_hooks is True, use base manager to avoid triggering hooks
|
|
57
58
|
if bypass_hooks:
|
|
58
59
|
return self._base_manager.save(self, *args, **kwargs)
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
is_create = self.pk is None
|
|
61
62
|
|
|
62
63
|
if is_create:
|
|
@@ -70,7 +71,8 @@ class HookModelMixin(models.Model):
|
|
|
70
71
|
else:
|
|
71
72
|
# For update operations, we need to get the old record
|
|
72
73
|
try:
|
|
73
|
-
|
|
74
|
+
# Use _base_manager to avoid triggering hooks recursively
|
|
75
|
+
old_instance = self.__class__._base_manager.get(pk=self.pk)
|
|
74
76
|
ctx = HookContext(self.__class__)
|
|
75
77
|
run(self.__class__, BEFORE_UPDATE, [self], [old_instance], ctx=ctx)
|
|
76
78
|
|
|
@@ -92,7 +94,7 @@ class HookModelMixin(models.Model):
|
|
|
92
94
|
# If bypass_hooks is True, use base manager to avoid triggering hooks
|
|
93
95
|
if bypass_hooks:
|
|
94
96
|
return self._base_manager.delete(self, *args, **kwargs)
|
|
95
|
-
|
|
97
|
+
|
|
96
98
|
ctx = HookContext(self.__class__)
|
|
97
99
|
|
|
98
100
|
# Run validation hooks first
|
|
@@ -24,8 +24,9 @@ class HookQuerySet(models.QuerySet):
|
|
|
24
24
|
objs = list(self)
|
|
25
25
|
if not objs:
|
|
26
26
|
return 0
|
|
27
|
-
#
|
|
28
|
-
|
|
27
|
+
# Use our bulk_delete method to handle hooks properly
|
|
28
|
+
self.bulk_delete(objs)
|
|
29
|
+
return len(objs)
|
|
29
30
|
|
|
30
31
|
@transaction.atomic
|
|
31
32
|
def update(self, **kwargs):
|
|
@@ -33,33 +34,28 @@ class HookQuerySet(models.QuerySet):
|
|
|
33
34
|
if not instances:
|
|
34
35
|
return 0
|
|
35
36
|
|
|
36
|
-
model_cls = self.model
|
|
37
|
-
pks = [obj.pk for obj in instances]
|
|
38
|
-
|
|
39
|
-
# Load originals for hook comparison and ensure they match the order of instances
|
|
40
|
-
# Use the base manager to avoid recursion
|
|
41
|
-
original_map = {
|
|
42
|
-
obj.pk: obj for obj in model_cls._base_manager.filter(pk__in=pks)
|
|
43
|
-
}
|
|
44
|
-
originals = [original_map.get(obj.pk) for obj in instances]
|
|
45
|
-
|
|
46
37
|
# Apply field updates to instances
|
|
47
38
|
for obj in instances:
|
|
48
39
|
for field, value in kwargs.items():
|
|
49
40
|
setattr(obj, field, value)
|
|
50
41
|
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
# Use Django's built-in update logic directly
|
|
56
|
-
# Call the base QuerySet implementation to avoid recursion
|
|
57
|
-
update_count = super().update(**kwargs)
|
|
42
|
+
# Use our bulk_update method to handle hooks properly
|
|
43
|
+
self.bulk_update(instances, list(kwargs.keys()))
|
|
44
|
+
return len(instances)
|
|
58
45
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
def save(self, obj):
|
|
47
|
+
"""
|
|
48
|
+
Save a single object using the appropriate bulk operation.
|
|
49
|
+
"""
|
|
50
|
+
if obj.pk:
|
|
51
|
+
# Use bulk_update for existing objects
|
|
52
|
+
self.bulk_update(
|
|
53
|
+
[obj], [field.name for field in obj._meta.fields if field.name != "id"]
|
|
54
|
+
)
|
|
55
|
+
else:
|
|
56
|
+
# Use bulk_create for new objects
|
|
57
|
+
self.bulk_create([obj])
|
|
58
|
+
return obj
|
|
63
59
|
|
|
64
60
|
@transaction.atomic
|
|
65
61
|
def bulk_create(
|
|
@@ -254,9 +250,23 @@ class HookQuerySet(models.QuerySet):
|
|
|
254
250
|
|
|
255
251
|
pks = [obj.pk for obj in objs if obj.pk is not None]
|
|
256
252
|
|
|
257
|
-
#
|
|
258
|
-
#
|
|
259
|
-
|
|
253
|
+
# Use Django's base manager to perform the actual deletion
|
|
254
|
+
# This avoids recursion and uses Django's built-in delete logic
|
|
255
|
+
from django.db.models import QuerySet
|
|
256
|
+
|
|
257
|
+
base_qs = QuerySet(model_cls, using=self.db)
|
|
258
|
+
|
|
259
|
+
# Delete in batches if batch_size is specified
|
|
260
|
+
if batch_size:
|
|
261
|
+
for i in range(0, len(objs), batch_size):
|
|
262
|
+
batch = objs[i : i + batch_size]
|
|
263
|
+
batch_pks = [obj.pk for obj in batch if obj.pk is not None]
|
|
264
|
+
if batch_pks:
|
|
265
|
+
base_qs.filter(pk__in=batch_pks).delete()
|
|
266
|
+
else:
|
|
267
|
+
# Delete all at once
|
|
268
|
+
if pks:
|
|
269
|
+
base_qs.filter(pk__in=pks).delete()
|
|
260
270
|
|
|
261
271
|
if not bypass_hooks:
|
|
262
272
|
engine.run(model_cls, AFTER_DELETE, objs, ctx=ctx)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "django-bulk-hooks"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.171"
|
|
4
4
|
description = "Hook-style hooks for Django bulk operations like bulk_create and bulk_update."
|
|
5
5
|
authors = ["Konrad Beck <konrad.beck@merchantcapital.co.za>"]
|
|
6
6
|
readme = "README.md"
|
|
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
|
|
File without changes
|