django-bulk-hooks 0.1.239__py3-none-any.whl → 0.1.240__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/queryset.py +67 -6
- {django_bulk_hooks-0.1.239.dist-info → django_bulk_hooks-0.1.240.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.1.239.dist-info → django_bulk_hooks-0.1.240.dist-info}/RECORD +5 -5
- {django_bulk_hooks-0.1.239.dist-info → django_bulk_hooks-0.1.240.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.1.239.dist-info → django_bulk_hooks-0.1.240.dist-info}/WHEEL +0 -0
django_bulk_hooks/queryset.py
CHANGED
|
@@ -55,6 +55,7 @@ class HookQuerySetMixin:
|
|
|
55
55
|
|
|
56
56
|
@transaction.atomic
|
|
57
57
|
def update(self, **kwargs):
|
|
58
|
+
logger.debug(f"Entering update method with {len(kwargs)} kwargs")
|
|
58
59
|
instances = list(self)
|
|
59
60
|
if not instances:
|
|
60
61
|
return 0
|
|
@@ -70,13 +71,29 @@ class HookQuerySetMixin:
|
|
|
70
71
|
originals = [original_map.get(obj.pk) for obj in instances]
|
|
71
72
|
|
|
72
73
|
# Check if any of the update values are Subquery objects
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
try:
|
|
75
|
+
from django.db.models import Subquery
|
|
76
|
+
logger.debug(f"Successfully imported Subquery from django.db.models")
|
|
77
|
+
except ImportError as e:
|
|
78
|
+
logger.error(f"Failed to import Subquery: {e}")
|
|
79
|
+
raise
|
|
80
|
+
|
|
81
|
+
logger.debug(f"Checking for Subquery objects in {len(kwargs)} kwargs")
|
|
82
|
+
|
|
83
|
+
subquery_detected = []
|
|
84
|
+
for key, value in kwargs.items():
|
|
85
|
+
is_subquery = isinstance(value, Subquery)
|
|
86
|
+
logger.debug(f"Key '{key}': type={type(value).__name__}, is_subquery={is_subquery}")
|
|
87
|
+
if is_subquery:
|
|
88
|
+
subquery_detected.append(key)
|
|
89
|
+
|
|
90
|
+
has_subquery = len(subquery_detected) > 0
|
|
91
|
+
logger.debug(f"Subquery detection result: {has_subquery}, detected keys: {subquery_detected}")
|
|
78
92
|
|
|
79
93
|
# Debug logging for Subquery detection
|
|
94
|
+
logger.debug(f"Update kwargs: {list(kwargs.keys())}")
|
|
95
|
+
logger.debug(f"Update kwargs types: {[(k, type(v).__name__) for k, v in kwargs.items()]}")
|
|
96
|
+
|
|
80
97
|
if has_subquery:
|
|
81
98
|
logger.debug(f"Detected Subquery in update: {[k for k, v in kwargs.items() if isinstance(v, Subquery)]}")
|
|
82
99
|
else:
|
|
@@ -84,6 +101,8 @@ class HookQuerySetMixin:
|
|
|
84
101
|
for k, v in kwargs.items():
|
|
85
102
|
if hasattr(v, 'query') and hasattr(v, 'resolve_expression'):
|
|
86
103
|
logger.warning(f"Potential Subquery-like object detected but not recognized: {k}={type(v).__name__}")
|
|
104
|
+
logger.warning(f"Object attributes: query={hasattr(v, 'query')}, resolve_expression={hasattr(v, 'resolve_expression')}")
|
|
105
|
+
logger.warning(f"Object dir: {[attr for attr in dir(v) if not attr.startswith('_')][:10]}")
|
|
87
106
|
|
|
88
107
|
# Apply field updates to instances
|
|
89
108
|
# If a per-object value map exists (from bulk_update), prefer it over kwargs
|
|
@@ -162,7 +181,49 @@ class HookQuerySetMixin:
|
|
|
162
181
|
|
|
163
182
|
# Use Django's built-in update logic directly
|
|
164
183
|
# Call the base QuerySet implementation to avoid recursion
|
|
165
|
-
|
|
184
|
+
|
|
185
|
+
# Additional safety check: ensure Subquery objects are properly handled
|
|
186
|
+
# This prevents the "cannot adapt type 'Subquery'" error
|
|
187
|
+
safe_kwargs = {}
|
|
188
|
+
logger.debug(f"Processing {len(kwargs)} kwargs for safety check")
|
|
189
|
+
|
|
190
|
+
for key, value in kwargs.items():
|
|
191
|
+
logger.debug(f"Processing key '{key}' with value type {type(value).__name__}")
|
|
192
|
+
|
|
193
|
+
if isinstance(value, Subquery):
|
|
194
|
+
logger.debug(f"Found Subquery for field {key}")
|
|
195
|
+
# Ensure Subquery has proper output_field
|
|
196
|
+
if not hasattr(value, 'output_field') or value.output_field is None:
|
|
197
|
+
logger.warning(f"Subquery for field {key} missing output_field, attempting to infer")
|
|
198
|
+
# Try to infer from the model field
|
|
199
|
+
try:
|
|
200
|
+
field = model_cls._meta.get_field(key)
|
|
201
|
+
logger.debug(f"Inferred field type: {type(field).__name__}")
|
|
202
|
+
value = value.resolve_expression(None, None)
|
|
203
|
+
value.output_field = field
|
|
204
|
+
logger.debug(f"Set output_field to {field}")
|
|
205
|
+
except Exception as e:
|
|
206
|
+
logger.error(f"Failed to infer output_field for Subquery on {key}: {e}")
|
|
207
|
+
raise
|
|
208
|
+
else:
|
|
209
|
+
logger.debug(f"Subquery for field {key} already has output_field: {value.output_field}")
|
|
210
|
+
safe_kwargs[key] = value
|
|
211
|
+
else:
|
|
212
|
+
logger.debug(f"Non-Subquery value for field {key}: {type(value).__name__}")
|
|
213
|
+
safe_kwargs[key] = value
|
|
214
|
+
|
|
215
|
+
logger.debug(f"Safe kwargs keys: {list(safe_kwargs.keys())}")
|
|
216
|
+
logger.debug(f"Safe kwargs types: {[(k, type(v).__name__) for k, v in safe_kwargs.items()]}")
|
|
217
|
+
|
|
218
|
+
logger.debug(f"Calling super().update() with {len(safe_kwargs)} kwargs")
|
|
219
|
+
try:
|
|
220
|
+
update_count = super().update(**safe_kwargs)
|
|
221
|
+
logger.debug(f"Super update successful, count: {update_count}")
|
|
222
|
+
except Exception as e:
|
|
223
|
+
logger.error(f"Super update failed: {e}")
|
|
224
|
+
logger.error(f"Exception type: {type(e).__name__}")
|
|
225
|
+
logger.error(f"Safe kwargs that caused failure: {safe_kwargs}")
|
|
226
|
+
raise
|
|
166
227
|
|
|
167
228
|
# If we used Subquery objects, refresh the instances to get computed values
|
|
168
229
|
if has_subquery and instances:
|
|
@@ -9,9 +9,9 @@ django_bulk_hooks/handler.py,sha256=Bx-W6yyiciKMyy-BRxUt3CmRPCrX9_LhQgU-5LaJTjg,
|
|
|
9
9
|
django_bulk_hooks/manager.py,sha256=nfWiwU5-yAoxdnQsUMohxtyCpkV0MBv6X3wmipr9eQY,3697
|
|
10
10
|
django_bulk_hooks/models.py,sha256=exnXYVKEVbYAXhChCP8VdWTnKCnm9DiTcokEIBee1I0,4350
|
|
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=bi8jE8yvl2ih0M3LbzW8TZvl7JFKbgysILRXIpci6KM,42055
|
|
13
13
|
django_bulk_hooks/registry.py,sha256=GRUTGVQEO2sdkC9OaZ9Q3U7mM-3Ix83uTyvrlTtpatw,1317
|
|
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.240.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
15
|
+
django_bulk_hooks-0.1.240.dist-info/METADATA,sha256=hkqwdtVcH2Te0py2ryH-RXgAJpX93e0IDFteueUBYtQ,9061
|
|
16
|
+
django_bulk_hooks-0.1.240.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
17
|
+
django_bulk_hooks-0.1.240.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|