django-bulk-hooks 0.1.98__py3-none-any.whl → 0.1.100__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.

@@ -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, '_state') and getattr(self._state, 'validating', False):
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(self.__class__, VALIDATE_UPDATE, [self], [old_instance], ctx=ctx)
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
- # Let Django save first to handle form validation
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(self.__class__, VALIDATE_UPDATE, [self], [old_instance], ctx=ctx)
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
  Metadata-Version: 2.1
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.98
3
+ Version: 0.1.100
4
4
  Summary: Hook-style hooks for Django bulk operations like bulk_create and bulk_update.
5
5
  Home-page: https://github.com/AugendLimited/django-bulk-hooks
6
6
  License: MIT
@@ -7,10 +7,10 @@ django_bulk_hooks/engine.py,sha256=qSBvBel3pBWVE92ZzgKjMn2ceQpA7FMws2uMXes1MkA,3
7
7
  django_bulk_hooks/enums.py,sha256=Zo8_tJzuzZ2IKfVc7gZ-0tWPT8q1QhqZbAyoh9ZVJbs,381
8
8
  django_bulk_hooks/handler.py,sha256=tdDolHAJ_Nd7-RT4s9HRyLtM1UWGjRjP1Y_U6Af32Gg,5325
9
9
  django_bulk_hooks/manager.py,sha256=DcVosEA4RS79KSYgw3Z14_a9Sd8CfxNNc5F3eSb8xc0,11459
10
- django_bulk_hooks/models.py,sha256=a9XoGgIG4Sfi_kvGnPBbG2DlvgZDz6Qck4VG-DGqFT0,4981
10
+ django_bulk_hooks/models.py,sha256=U5nCxingZS2sznDjgW8fWo93SisA03WKcGpxxApqhuM,5519
11
11
  django_bulk_hooks/queryset.py,sha256=7lLqhZ-XOYsZ1I3Loxi4Nhz79M8HlTYE413AW8nyeDI,1330
12
12
  django_bulk_hooks/registry.py,sha256=Vh78exKYcdZhM27120kQm-iXGOjd_kf9ZUYBZ8eQ2V0,683
13
- django_bulk_hooks-0.1.98.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
14
- django_bulk_hooks-0.1.98.dist-info/METADATA,sha256=KLEuzqcEjYRTaH3rhRfoyQIGkbNQwhA0KL1HniVfHzM,15414
15
- django_bulk_hooks-0.1.98.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
- django_bulk_hooks-0.1.98.dist-info/RECORD,,
13
+ django_bulk_hooks-0.1.100.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
14
+ django_bulk_hooks-0.1.100.dist-info/METADATA,sha256=AH1pPY4iPjCTvBY5Vyj4dWYJeU5CELEkVt0uRdiW2bg,15415
15
+ django_bulk_hooks-0.1.100.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
+ django_bulk_hooks-0.1.100.dist-info/RECORD,,