django-bulk-hooks 0.2.8__tar.gz → 0.2.9__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.

Files changed (26) hide show
  1. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/PKG-INFO +1 -1
  2. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/operations/analyzer.py +63 -1
  3. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/pyproject.toml +1 -1
  4. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/LICENSE +0 -0
  5. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/README.md +0 -0
  6. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/__init__.py +0 -0
  7. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/changeset.py +0 -0
  8. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/conditions.py +0 -0
  9. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/constants.py +0 -0
  10. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/context.py +0 -0
  11. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/debug_utils.py +0 -0
  12. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/decorators.py +0 -0
  13. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/dispatcher.py +0 -0
  14. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/enums.py +0 -0
  15. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/factory.py +0 -0
  16. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/handler.py +0 -0
  17. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/helpers.py +0 -0
  18. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/manager.py +0 -0
  19. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/models.py +0 -0
  20. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/operations/__init__.py +0 -0
  21. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/operations/bulk_executor.py +0 -0
  22. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/operations/coordinator.py +0 -0
  23. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/operations/mti_handler.py +0 -0
  24. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/operations/mti_plans.py +0 -0
  25. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/queryset.py +0 -0
  26. {django_bulk_hooks-0.2.8 → django_bulk_hooks-0.2.9}/django_bulk_hooks/registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-bulk-hooks
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary: Hook-style hooks for Django bulk operations like bulk_create and bulk_update.
5
5
  License: MIT
6
6
  Keywords: django,bulk,hooks
@@ -257,6 +257,10 @@ class ModelAnalyzer:
257
257
  F() expressions, Subquery, Case, etc.) into concrete values and applies
258
258
  them to the instances.
259
259
 
260
+ CRITICAL: When setting FK fields by their attname (e.g., business_id),
261
+ we must manually clear the relationship cache (e.g., business) to match
262
+ Django's ForeignKey descriptor behavior.
263
+
260
264
  Args:
261
265
  instances: List of model instances to update
262
266
  update_kwargs: Dict of {field_name: value_or_expression}
@@ -270,8 +274,66 @@ class ModelAnalyzer:
270
274
  fields_updated = list(update_kwargs.keys())
271
275
 
272
276
  for field_name, value in update_kwargs.items():
277
+ # Determine if this is a FK field being set by its attname
278
+ field_info = self._get_fk_field_info(field_name)
279
+
273
280
  for instance in instances:
274
281
  resolved_value = self.resolve_expression(field_name, value, instance)
275
282
  setattr(instance, field_name, resolved_value)
283
+
284
+ # Clear relationship cache when FK field is set directly
285
+ # This replicates Django's ForeignKey descriptor behavior
286
+ if field_info and field_info['is_fk_attname']:
287
+ self._clear_fk_cache(instance, field_info['accessor_name'])
288
+
289
+ return fields_updated
290
+
291
+ def _get_fk_field_info(self, field_name):
292
+ """
293
+ Get information about a FK field if field_name is a FK attname.
294
+
295
+ Args:
296
+ field_name: Field name to check
297
+
298
+ Returns:
299
+ Dict with FK info or None if not a FK field
300
+ """
301
+ try:
302
+ # Check all fields to find if this is a FK attname
303
+ for field in self.model_cls._meta.get_fields():
304
+ if (field.is_relation and
305
+ not field.many_to_many and
306
+ not field.one_to_many and
307
+ hasattr(field, 'attname') and
308
+ field.attname == field_name):
309
+ # This is a FK field being set by its attname (e.g., business_id)
310
+ return {
311
+ 'is_fk_attname': True,
312
+ 'accessor_name': field.name, # e.g., 'business'
313
+ 'field': field
314
+ }
315
+ except Exception as e:
316
+ logger.debug(f"Error checking FK field info for {field_name}: {e}")
317
+
318
+ return None
319
+
320
+ def _clear_fk_cache(self, instance, accessor_name):
321
+ """
322
+ Clear cached relationship when FK field is set directly.
276
323
 
277
- return fields_updated
324
+ This replicates what Django's ForeignKey descriptor __set__ does:
325
+ when you set a FK field, Django clears the cached related object.
326
+
327
+ Args:
328
+ instance: Model instance
329
+ accessor_name: Name of the relationship accessor (e.g., 'business')
330
+ """
331
+ try:
332
+ if hasattr(instance, '_state') and hasattr(instance._state, 'fields_cache'):
333
+ instance._state.fields_cache.pop(accessor_name, None)
334
+ logger.debug(
335
+ f"Cleared FK cache for '{accessor_name}' on {self.model_cls.__name__}"
336
+ )
337
+ except Exception as e:
338
+ # Don't fail the operation, just log
339
+ logger.debug(f"Could not clear FK cache for {accessor_name}: {e}")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.2.8"
3
+ version = "0.2.9"
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"