django-bulk-hooks 0.1.261__tar.gz → 0.1.263__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.261 → django_bulk_hooks-0.1.263}/PKG-INFO +2 -2
  2. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/decorators.py +17 -12
  3. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/queryset.py +5 -4
  4. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/pyproject.toml +2 -2
  5. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/LICENSE +0 -0
  6. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/README.md +0 -0
  7. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/__init__.py +0 -0
  8. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/conditions.py +0 -0
  9. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/constants.py +0 -0
  10. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/context.py +0 -0
  11. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/engine.py +0 -0
  12. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/enums.py +0 -0
  13. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/handler.py +0 -0
  14. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/manager.py +0 -0
  15. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/models.py +0 -0
  16. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/django_bulk_hooks/priority.py +0 -0
  17. {django_bulk_hooks-0.1.261 → django_bulk_hooks-0.1.263}/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.1.261
3
+ Version: 0.1.263
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
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
- Requires-Dist: Django (>=4.0)
15
+ Requires-Dist: django (>=5.2.0,<6.0.0)
16
16
  Project-URL: Homepage, https://github.com/AugendLimited/django-bulk-hooks
17
17
  Project-URL: Repository, https://github.com/AugendLimited/django-bulk-hooks
18
18
  Description-Content-Type: text/markdown
@@ -82,17 +82,18 @@ def select_related(*related_fields):
82
82
  ids_to_fetch.append(obj.pk)
83
83
 
84
84
  # Always validate fields for nested field errors, regardless of whether we need to fetch
85
- for field in related_fields:
86
- if "." in field or "__" in field:
87
- raise ValueError(
88
- f"@select_related does not support nested fields like '{field}'"
89
- )
85
+ # Note: We allow nested fields as Django's select_related supports them
90
86
 
91
87
  fetched = {}
92
88
  if ids_to_fetch:
93
89
  # Validate fields before passing to select_related
94
90
  validated_fields = []
95
91
  for field in related_fields:
92
+ # For nested fields (containing __), let Django's select_related handle validation
93
+ if "__" in field:
94
+ validated_fields.append(field)
95
+ continue
96
+
96
97
  try:
97
98
  # Handle Mock objects that don't have _meta
98
99
  if hasattr(model_cls, "_meta"):
@@ -112,9 +113,13 @@ def select_related(*related_fields):
112
113
 
113
114
  if validated_fields:
114
115
  # Use the base manager to avoid recursion
115
- fetched = model_cls._base_manager.select_related(
116
- *validated_fields
117
- ).in_bulk(ids_to_fetch)
116
+ try:
117
+ fetched = model_cls._base_manager.select_related(
118
+ *validated_fields
119
+ ).in_bulk(ids_to_fetch)
120
+ except Exception:
121
+ # If select_related fails (e.g., invalid nested fields), skip preloading
122
+ fetched = {}
118
123
 
119
124
  for obj in new_records:
120
125
  preloaded = fetched.get(obj.pk)
@@ -126,8 +131,8 @@ def select_related(*related_fields):
126
131
  if field in obj._state.fields_cache:
127
132
  # don't override values that were explicitly set or already loaded
128
133
  continue
129
- if "." in field or "__" in field:
130
- # This should have been caught earlier, but just in case
134
+ if "." in field:
135
+ # Skip fields with dots (legacy format, not supported)
131
136
  continue
132
137
 
133
138
  try:
@@ -181,8 +186,8 @@ def bulk_hook(model_cls, event, when=None, priority=None):
181
186
  def __init__(self):
182
187
  self.func = func
183
188
 
184
- def handle(self, new_instances, original_instances):
185
- return self.func(new_instances, original_instances)
189
+ def handle(self, new_records=None, old_records=None, **kwargs):
190
+ return self.func(new_records, old_records)
186
191
 
187
192
  # Register the hook using the registry
188
193
  register_hook(
@@ -889,6 +889,7 @@ class HookQuerySetMixin:
889
889
  # Handle auto_now fields like Django's update_or_create does
890
890
  fields_set = set(fields)
891
891
  pk_fields = model_cls._meta.pk_fields
892
+ pk_field_names = [f.name for f in pk_fields]
892
893
  auto_now_fields = []
893
894
  custom_update_fields = [] # Fields that need pre_save() called on update
894
895
  logger.debug(f"Checking for auto_now and custom update fields in {model_cls.__name__}")
@@ -898,7 +899,7 @@ class HookQuerySetMixin:
898
899
  if hasattr(field, "auto_now") and field.auto_now:
899
900
  logger.debug(f"Found auto_now field: {field.name}")
900
901
  print(f"DEBUG: Found auto_now field: {field.name}")
901
- if field.name not in fields_set and field.name not in pk_fields:
902
+ if field.name not in fields_set and field.name not in pk_field_names:
902
903
  fields_set.add(field.name)
903
904
  if field.name != field.attname:
904
905
  fields_set.add(field.attname)
@@ -913,7 +914,7 @@ class HookQuerySetMixin:
913
914
  # Check for custom fields that might need pre_save() on update (like CurrentUserField)
914
915
  elif hasattr(field, 'pre_save'):
915
916
  # Only call pre_save on fields that aren't already being updated
916
- if field.name not in fields_set and field.name not in pk_fields:
917
+ if field.name not in fields_set and field.name not in pk_field_names:
917
918
  custom_update_fields.append(field)
918
919
  logger.debug(f"Found custom field with pre_save: {field.name}")
919
920
  print(f"DEBUG: Found custom field with pre_save: {field.name}")
@@ -945,8 +946,8 @@ class HookQuerySetMixin:
945
946
  # Only update the field if pre_save returned a new value
946
947
  if new_value is not None:
947
948
  setattr(obj, field.name, new_value)
948
- # Add this field to the update fields if it's not already there
949
- if field.name not in fields_set:
949
+ # Add this field to the update fields if it's not already there and not a primary key
950
+ if field.name not in fields_set and field.name not in pk_field_names:
950
951
  fields_set.add(field.name)
951
952
  fields.append(field.name)
952
953
  logger.debug(f"Custom field {field.name} updated via pre_save() for object {obj.pk}")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.1.261"
3
+ version = "0.1.263"
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"
@@ -14,7 +14,7 @@ packages = [
14
14
 
15
15
  [tool.poetry.dependencies]
16
16
  python = "^3.11"
17
- Django = ">=4.0"
17
+ django = "^5.2.0"
18
18
 
19
19
  [tool.poetry.group.dev.dependencies]
20
20
  pytest = "^7.4.0"