django-bulk-hooks 0.1.184__tar.gz → 0.1.185__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.184 → django_bulk_hooks-0.1.185}/PKG-INFO +1 -1
  2. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/queryset.py +39 -6
  3. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/pyproject.toml +1 -1
  4. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/LICENSE +0 -0
  5. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/README.md +0 -0
  6. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/__init__.py +0 -0
  7. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/conditions.py +0 -0
  8. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/constants.py +0 -0
  9. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/context.py +0 -0
  10. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/decorators.py +0 -0
  11. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/engine.py +0 -0
  12. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/enums.py +0 -0
  13. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/handler.py +0 -0
  14. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/manager.py +0 -0
  15. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/models.py +0 -0
  16. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/django_bulk_hooks/priority.py +0 -0
  17. {django_bulk_hooks-0.1.184 → django_bulk_hooks-0.1.185}/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.184
3
+ Version: 0.1.185
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
@@ -537,6 +537,19 @@ class HookQuerySet(models.QuerySet):
537
537
  model_cls = self.model
538
538
  inheritance_chain = self._get_inheritance_chain()
539
539
 
540
+ # Remove custom hook kwargs before passing to Django internals
541
+ django_kwargs = {
542
+ k: v
543
+ for k, v in kwargs.items()
544
+ if k not in ["bypass_hooks", "bypass_validation"]
545
+ }
546
+
547
+ # Safety check to prevent infinite recursion
548
+ if len(inheritance_chain) > 10: # Arbitrary limit to prevent infinite loops
549
+ raise ValueError(
550
+ "Inheritance chain too deep - possible infinite recursion detected"
551
+ )
552
+
540
553
  # Group fields by model in the inheritance chain
541
554
  field_groups = {}
542
555
  for field_name in fields:
@@ -549,8 +562,28 @@ class HookQuerySet(models.QuerySet):
549
562
  field_groups[model].append(field_name)
550
563
  break
551
564
 
552
- # Update each table in the inheritance chain
565
+ # Process in batches
566
+ batch_size = django_kwargs.get("batch_size") or len(objs)
553
567
  total_updated = 0
568
+
569
+ with transaction.atomic(using=self.db, savepoint=False):
570
+ for i in range(0, len(objs), batch_size):
571
+ batch = objs[i : i + batch_size]
572
+ batch_result = self._process_mti_bulk_update_batch(
573
+ batch, field_groups, inheritance_chain, **django_kwargs
574
+ )
575
+ total_updated += batch_result
576
+
577
+ return total_updated
578
+
579
+ def _process_mti_bulk_update_batch(self, batch, field_groups, inheritance_chain, **kwargs):
580
+ """
581
+ Process a single batch of objects for MTI bulk update.
582
+ Updates each table in the inheritance chain for the batch.
583
+ """
584
+ total_updated = 0
585
+
586
+ # Update each table in the inheritance chain
554
587
  for model, model_fields in field_groups.items():
555
588
  if not model_fields:
556
589
  continue
@@ -560,7 +593,7 @@ class HookQuerySet(models.QuerySet):
560
593
  # Child models use the parent link to reference the root PK
561
594
  if model == inheritance_chain[0]:
562
595
  # Root model - use primary keys directly
563
- pks = [obj.pk for obj in objs]
596
+ pks = [obj.pk for obj in batch]
564
597
  filter_field = 'pk'
565
598
  else:
566
599
  # Child model - use parent link field
@@ -575,25 +608,25 @@ class HookQuerySet(models.QuerySet):
575
608
  continue
576
609
 
577
610
  # Get the parent link values (these should be the same as the root PKs)
578
- pks = [getattr(obj, parent_link.attname) for obj in objs]
611
+ pks = [getattr(obj, parent_link.attname) for obj in batch]
579
612
  filter_field = parent_link.attname
580
613
 
581
614
  if pks:
582
615
  base_qs = model._base_manager.using(self.db)
583
616
 
584
- # Build CASE statements for each field
617
+ # Build CASE statements for each field to perform a single bulk update
585
618
  case_statements = {}
586
619
  for field_name in model_fields:
587
620
  field = model._meta.get_field(field_name)
588
621
  when_statements = []
589
622
 
590
- for pk, obj in zip(pks, objs):
623
+ for pk, obj in zip(pks, batch):
591
624
  value = getattr(obj, field_name)
592
625
  when_statements.append(When(**{filter_field: pk}, then=Value(value, output_field=field)))
593
626
 
594
627
  case_statements[field_name] = Case(*when_statements, output_field=field)
595
628
 
596
- # Execute the update using the appropriate filter field
629
+ # Execute a single bulk update for all objects in this model
597
630
  updated_count = base_qs.filter(**{f"{filter_field}__in": pks}).update(**case_statements)
598
631
  total_updated += updated_count
599
632
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.1.184"
3
+ version = "0.1.185"
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"