django-bulk-hooks 0.1.98__tar.gz → 0.1.100__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.98 → django_bulk_hooks-0.1.100}/PKG-INFO +1 -1
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/models.py +31 -15
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/pyproject.toml +1 -1
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/LICENSE +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/README.md +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/engine.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/queryset.py +0 -0
- {django_bulk_hooks-0.1.98 → django_bulk_hooks-0.1.100}/django_bulk_hooks/registry.py +0 -0
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
from functools import wraps
|
|
3
|
+
|
|
1
4
|
from django.db import models, transaction
|
|
5
|
+
from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor
|
|
2
6
|
|
|
3
7
|
from django_bulk_hooks.constants import (
|
|
4
8
|
AFTER_CREATE,
|
|
@@ -14,9 +18,6 @@ from django_bulk_hooks.constants import (
|
|
|
14
18
|
from django_bulk_hooks.context import HookContext
|
|
15
19
|
from django_bulk_hooks.engine import run
|
|
16
20
|
from django_bulk_hooks.manager import BulkHookManager
|
|
17
|
-
from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor
|
|
18
|
-
from functools import wraps
|
|
19
|
-
import contextlib
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
@contextlib.contextmanager
|
|
@@ -26,7 +27,7 @@ def patch_foreign_key_behavior():
|
|
|
26
27
|
RelatedObjectDoesNotExist when accessing an unset foreign key field.
|
|
27
28
|
"""
|
|
28
29
|
original_get = ForwardManyToOneDescriptor.__get__
|
|
29
|
-
|
|
30
|
+
|
|
30
31
|
@wraps(original_get)
|
|
31
32
|
def safe_get(self, instance, cls=None):
|
|
32
33
|
if instance is None:
|
|
@@ -35,7 +36,7 @@ def patch_foreign_key_behavior():
|
|
|
35
36
|
return original_get(self, instance, cls)
|
|
36
37
|
except self.RelatedObjectDoesNotExist:
|
|
37
38
|
return None
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
# Patch the descriptor
|
|
40
41
|
ForwardManyToOneDescriptor.__get__ = safe_get
|
|
41
42
|
try:
|
|
@@ -63,7 +64,7 @@ class HookModelMixin(models.Model):
|
|
|
63
64
|
# Skip hook validation during admin form validation
|
|
64
65
|
# This prevents RelatedObjectDoesNotExist errors when Django hasn't
|
|
65
66
|
# fully set up the object's relationships yet
|
|
66
|
-
if hasattr(self,
|
|
67
|
+
if hasattr(self, "_state") and getattr(self._state, "validating", False):
|
|
67
68
|
return
|
|
68
69
|
|
|
69
70
|
# Determine if this is a create or update operation
|
|
@@ -80,7 +81,9 @@ class HookModelMixin(models.Model):
|
|
|
80
81
|
old_instance = self.__class__.objects.get(pk=self.pk)
|
|
81
82
|
ctx = HookContext(self.__class__)
|
|
82
83
|
with patch_foreign_key_behavior():
|
|
83
|
-
run(
|
|
84
|
+
run(
|
|
85
|
+
self.__class__, VALIDATE_UPDATE, [self], [old_instance], ctx=ctx
|
|
86
|
+
)
|
|
84
87
|
except self.__class__.DoesNotExist:
|
|
85
88
|
# If the old instance doesn't exist, treat as create
|
|
86
89
|
ctx = HookContext(self.__class__)
|
|
@@ -91,27 +94,40 @@ class HookModelMixin(models.Model):
|
|
|
91
94
|
is_create = self.pk is None
|
|
92
95
|
ctx = HookContext(self.__class__)
|
|
93
96
|
|
|
94
|
-
#
|
|
95
|
-
super().save(*args, **kwargs)
|
|
96
|
-
|
|
97
|
-
# Then run our hooks with the validated data
|
|
97
|
+
# Run BEFORE hooks before saving to allow field modifications
|
|
98
98
|
with patch_foreign_key_behavior():
|
|
99
99
|
if is_create:
|
|
100
100
|
# For create operations
|
|
101
101
|
run(self.__class__, VALIDATE_CREATE, [self], ctx=ctx)
|
|
102
102
|
run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
|
|
103
|
-
run(self.__class__, AFTER_CREATE, [self], ctx=ctx)
|
|
104
103
|
else:
|
|
105
104
|
# For update operations
|
|
106
105
|
try:
|
|
107
106
|
old_instance = self.__class__.objects.get(pk=self.pk)
|
|
108
|
-
run(
|
|
107
|
+
run(
|
|
108
|
+
self.__class__, VALIDATE_UPDATE, [self], [old_instance], ctx=ctx
|
|
109
|
+
)
|
|
109
110
|
run(self.__class__, BEFORE_UPDATE, [self], [old_instance], ctx=ctx)
|
|
110
|
-
run(self.__class__, AFTER_UPDATE, [self], [old_instance], ctx=ctx)
|
|
111
111
|
except self.__class__.DoesNotExist:
|
|
112
112
|
# If the old instance doesn't exist, treat as create
|
|
113
113
|
run(self.__class__, VALIDATE_CREATE, [self], ctx=ctx)
|
|
114
114
|
run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
|
|
115
|
+
|
|
116
|
+
# Now let Django save with any modifications from BEFORE hooks
|
|
117
|
+
super().save(*args, **kwargs)
|
|
118
|
+
|
|
119
|
+
# Then run AFTER hooks
|
|
120
|
+
with patch_foreign_key_behavior():
|
|
121
|
+
if is_create:
|
|
122
|
+
# For create operations
|
|
123
|
+
run(self.__class__, AFTER_CREATE, [self], ctx=ctx)
|
|
124
|
+
else:
|
|
125
|
+
# For update operations
|
|
126
|
+
try:
|
|
127
|
+
old_instance = self.__class__.objects.get(pk=self.pk)
|
|
128
|
+
run(self.__class__, AFTER_UPDATE, [self], [old_instance], ctx=ctx)
|
|
129
|
+
except self.__class__.DoesNotExist:
|
|
130
|
+
# If the old instance doesn't exist, treat as create
|
|
115
131
|
run(self.__class__, AFTER_CREATE, [self], ctx=ctx)
|
|
116
132
|
|
|
117
133
|
return self
|
|
@@ -125,5 +141,5 @@ class HookModelMixin(models.Model):
|
|
|
125
141
|
run(self.__class__, BEFORE_DELETE, [self], ctx=ctx)
|
|
126
142
|
result = super().delete(*args, **kwargs)
|
|
127
143
|
run(self.__class__, AFTER_DELETE, [self], ctx=ctx)
|
|
128
|
-
|
|
144
|
+
|
|
129
145
|
return result
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "django-bulk-hooks"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.100"
|
|
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
|