django-bulk-hooks 0.1.225__tar.gz → 0.1.226__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 (17) hide show
  1. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/PKG-INFO +1 -1
  2. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/models.py +3 -0
  3. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/queryset.py +22 -6
  4. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/pyproject.toml +1 -1
  5. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/LICENSE +0 -0
  6. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/README.md +0 -0
  7. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/__init__.py +0 -0
  8. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/conditions.py +0 -0
  9. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/constants.py +0 -0
  10. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/context.py +0 -0
  11. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/decorators.py +0 -0
  12. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/engine.py +0 -0
  13. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/enums.py +0 -0
  14. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/handler.py +0 -0
  15. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/manager.py +0 -0
  16. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/priority.py +0 -0
  17. {django_bulk_hooks-0.1.225 → django_bulk_hooks-0.1.226}/django_bulk_hooks/registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.225
3
+ Version: 0.1.226
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
@@ -68,6 +68,7 @@ class HookModelMixin(models.Model):
68
68
  logger.debug(f"save() creating new {self.__class__.__name__} instance")
69
69
  # For create operations, we don't have old records
70
70
  ctx = HookContext(self.__class__)
71
+ run(self.__class__, VALIDATE_CREATE, [self], ctx=ctx)
71
72
  run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
72
73
 
73
74
  super().save(*args, **kwargs)
@@ -80,6 +81,7 @@ class HookModelMixin(models.Model):
80
81
  # Use _base_manager to avoid triggering hooks recursively
81
82
  old_instance = self.__class__._base_manager.get(pk=self.pk)
82
83
  ctx = HookContext(self.__class__)
84
+ run(self.__class__, VALIDATE_UPDATE, [self], [old_instance], ctx=ctx)
83
85
  run(self.__class__, BEFORE_UPDATE, [self], [old_instance], ctx=ctx)
84
86
 
85
87
  super().save(*args, **kwargs)
@@ -88,6 +90,7 @@ class HookModelMixin(models.Model):
88
90
  except self.__class__.DoesNotExist:
89
91
  # If the old instance doesn't exist, treat as create
90
92
  ctx = HookContext(self.__class__)
93
+ run(self.__class__, VALIDATE_CREATE, [self], ctx=ctx)
91
94
  run(self.__class__, BEFORE_CREATE, [self], ctx=ctx)
92
95
 
93
96
  super().save(*args, **kwargs)
@@ -65,11 +65,27 @@ class HookQuerySetMixin:
65
65
  }
66
66
  originals = [original_map.get(obj.pk) for obj in instances]
67
67
 
68
- # Check if any of the update values are Subquery objects
68
+ # Check if any of the update values are complex database expressions (Subquery, Case, etc.)
69
69
  has_subquery = any(
70
- hasattr(value, "query") and hasattr(value, "resolve_expression")
70
+ (hasattr(value, "query") and hasattr(value, "resolve_expression"))
71
+ or hasattr(
72
+ value, "resolve_expression"
73
+ ) # This catches Case, F expressions, etc.
71
74
  for value in kwargs.values()
72
75
  )
76
+
77
+ # Also check if any of the instances have complex expressions in their attributes
78
+ # This can happen when bulk_update creates Case expressions and applies them to instances
79
+ if not has_subquery and instances:
80
+ for instance in instances:
81
+ for field_name in kwargs.keys():
82
+ if hasattr(instance, field_name):
83
+ field_value = getattr(instance, field_name)
84
+ if hasattr(field_value, "resolve_expression"):
85
+ has_subquery = True
86
+ break
87
+ if has_subquery:
88
+ break
73
89
 
74
90
  # Check if we're in a bulk operation context to prevent double hook execution
75
91
  from django_bulk_hooks.context import get_bypass_hooks
@@ -98,11 +114,11 @@ class HookQuerySetMixin:
98
114
  engine.run(
99
115
  model_cls, VALIDATE_UPDATE, instances, originals, ctx=ctx
100
116
  )
101
- except (TypeError, ValueError) as e:
102
- # If validation fails due to Subquery comparison, skip validation for subquery updates
103
- # This is a limitation - validation hooks cannot easily work with unresolved subqueries
117
+ except (TypeError, ValueError, AttributeError) as e:
118
+ # If validation fails due to Subquery/Case comparison, skip validation for complex updates
119
+ # This is a limitation - validation hooks cannot easily work with unresolved database expressions
104
120
  logger.warning(
105
- f"Skipping validation hooks for subquery update due to: {e}"
121
+ f"Skipping validation hooks for complex update due to: {e}"
106
122
  )
107
123
 
108
124
  # Execute the database update first to compute subquery values
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.1.225"
3
+ version = "0.1.226"
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"