django-bulk-hooks 0.1.145__tar.gz → 0.1.147__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.145 → django_bulk_hooks-0.1.147}/PKG-INFO +1 -1
  2. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/queryset.py +4 -49
  3. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/pyproject.toml +1 -1
  4. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/LICENSE +0 -0
  5. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/README.md +0 -0
  6. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/__init__.py +0 -0
  7. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/conditions.py +0 -0
  8. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/constants.py +0 -0
  9. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/context.py +0 -0
  10. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/decorators.py +0 -0
  11. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/engine.py +0 -0
  12. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/enums.py +0 -0
  13. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/handler.py +0 -0
  14. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/manager.py +0 -0
  15. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/models.py +0 -0
  16. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/django_bulk_hooks/priority.py +0 -0
  17. {django_bulk_hooks-0.1.145 → django_bulk_hooks-0.1.147}/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.145
3
+ Version: 0.1.147
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
@@ -97,15 +97,10 @@ class HookQuerySet(models.QuerySet):
97
97
  # MultiTableParent -> ProxyChild. Simply checking self.model._meta.proxy would not
98
98
  # identify that case as involving multiple tables.
99
99
  is_mti = False
100
- print(f"DEBUG: Checking for MTI on {model_cls.__name__}")
101
- print(f"DEBUG: All parents: {[p.__name__ for p in model_cls._meta.all_parents]}")
102
100
  for parent in model_cls._meta.all_parents:
103
- print(f"DEBUG: Checking parent {parent.__name__} (concrete: {parent._meta.concrete_model.__name__}) vs {model_cls.__name__} (concrete: {model_cls._meta.concrete_model.__name__})")
104
101
  if parent._meta.concrete_model is not model_cls._meta.concrete_model:
105
102
  is_mti = True
106
- print(f"DEBUG: MTI detected! {parent.__name__} and {model_cls.__name__} have different concrete models")
107
103
  break
108
- print(f"DEBUG: Final MTI result: {is_mti}")
109
104
 
110
105
  if not objs:
111
106
  return objs
@@ -124,7 +119,6 @@ class HookQuerySet(models.QuerySet):
124
119
 
125
120
  # For MTI models, we need to handle them specially
126
121
  if is_mti:
127
- print(f"DEBUG: Using MTI-specific logic for {model_cls.__name__}")
128
122
  # Use our MTI-specific logic
129
123
  result = self._mti_bulk_create(
130
124
  objs,
@@ -135,7 +129,6 @@ class HookQuerySet(models.QuerySet):
135
129
  unique_fields=unique_fields,
136
130
  )
137
131
  else:
138
- print(f"DEBUG: Using standard bulk_create for {model_cls.__name__}")
139
132
  # For single-table models, use Django's built-in bulk_create
140
133
  # but we need to call it on the base manager to avoid recursion
141
134
 
@@ -332,13 +325,10 @@ class HookQuerySet(models.QuerySet):
332
325
  parent_objects_map = {}
333
326
 
334
327
  # Step 1: Do O(n) normal inserts into parent tables to get primary keys back
335
- print(f"DEBUG: Processing batch of {len(batch)} objects")
336
- print(f"DEBUG: Inheritance chain: {[m.__name__ for m in inheritance_chain]}")
337
328
  for obj in batch:
338
329
  parent_instances = {}
339
330
  current_parent = None
340
331
  for model_class in inheritance_chain[:-1]:
341
- print(f"DEBUG: Creating parent instance for {model_class.__name__}")
342
332
  parent_obj = self._create_parent_instance(
343
333
  obj, model_class, current_parent
344
334
  )
@@ -349,9 +339,7 @@ class HookQuerySet(models.QuerySet):
349
339
  for field in model_class._meta.local_fields
350
340
  if hasattr(parent_obj, field.name) and getattr(parent_obj, field.name) is not None
351
341
  }
352
- print(f"DEBUG: Creating {model_class.__name__} with field_values: {field_values}")
353
342
  created_obj = model_class._base_manager.using(self.db).create(**field_values)
354
- print(f"DEBUG: Created {model_class.__name__} with PK: {created_obj.pk}")
355
343
  # Update the parent_obj with the created object's PK
356
344
  parent_obj.pk = created_obj.pk
357
345
  parent_obj._state.adding = False
@@ -362,19 +350,15 @@ class HookQuerySet(models.QuerySet):
362
350
 
363
351
  # Step 2: Create all child objects and do single bulk insert into childmost table
364
352
  child_model = inheritance_chain[-1]
365
- print(f"DEBUG: Creating child objects for {child_model.__name__}")
366
353
  all_child_objects = []
367
354
  for obj in batch:
368
355
  child_obj = self._create_child_instance(
369
356
  obj, child_model, parent_objects_map.get(id(obj), {})
370
357
  )
371
358
  all_child_objects.append(child_obj)
372
- print(f"DEBUG: Created {len(all_child_objects)} child objects")
373
359
 
374
360
  # Step 2.5: Use Django's internal bulk_create infrastructure
375
361
  if all_child_objects:
376
- print(f"DEBUG: Using Django's internal bulk_create infrastructure for {len(all_child_objects)} child objects")
377
-
378
362
  # Get the base manager's queryset
379
363
  base_qs = child_model._base_manager.using(self.db)
380
364
 
@@ -389,38 +373,17 @@ class HookQuerySet(models.QuerySet):
389
373
  else:
390
374
  objs_without_pk.append(obj)
391
375
 
392
- print(f"DEBUG: Prepared {len(objs_with_pk)} objects with PK, {len(objs_without_pk)} objects without PK")
393
-
394
376
  # Use Django's internal _batched_insert method
395
377
  opts = child_model._meta
396
378
  # For child models in MTI, we need to include the foreign key to the parent
397
379
  # but exclude the primary key since it's inherited
398
- print(f"DEBUG: All local fields: {[f.name for f in opts.local_fields]}")
399
380
 
400
381
  # Include all local fields except generated ones
401
382
  # We need to include the foreign key to the parent (business_ptr)
402
383
  fields = [f for f in opts.local_fields if not f.generated]
403
- print(f"DEBUG: Child model fields to insert: {[f.name for f in fields]}")
404
-
405
- # Debug: Check what fields are actually set on the child objects
406
- for i, child_obj in enumerate(all_child_objects[:3]): # Check first 3 objects
407
- print(f"DEBUG: Child object {i} fields: {[f.name for f in child_model._meta.local_fields if hasattr(child_obj, f.name) and getattr(child_obj, f.name) is not None]}")
408
- # Debug: Check the actual values
409
- for field in child_model._meta.local_fields:
410
- if hasattr(child_obj, field.name) and getattr(child_obj, field.name) is not None:
411
- value = getattr(child_obj, field.name)
412
- if hasattr(value, 'pk'):
413
- print(f"DEBUG: Child object {i} {field.name} = {value} (PK: {value.pk})")
414
- else:
415
- print(f"DEBUG: Child object {i} {field.name} = {value}")
416
-
417
- # Debug: Check what fields are actually set on the child objects
418
- for i, child_obj in enumerate(all_child_objects[:3]): # Check first 3 objects
419
- print(f"DEBUG: Child object {i} fields: {[f.name for f in child_model._meta.local_fields if hasattr(child_obj, f.name) and getattr(child_obj, f.name) is not None]}")
420
384
 
421
385
  with transaction.atomic(using=self.db, savepoint=False):
422
386
  if objs_with_pk:
423
- print(f"DEBUG: Inserting {len(objs_with_pk)} objects with PK")
424
387
  returned_columns = base_qs._batched_insert(
425
388
  objs_with_pk,
426
389
  fields,
@@ -435,7 +398,6 @@ class HookQuerySet(models.QuerySet):
435
398
  obj_with_pk._state.db = self.db
436
399
 
437
400
  if objs_without_pk:
438
- print(f"DEBUG: Inserting {len(objs_without_pk)} objects without PK")
439
401
  # For objects without PK, we still need to exclude primary key fields
440
402
  fields = [f for f in fields if not isinstance(f, AutoField) and not f.primary_key]
441
403
  returned_columns = base_qs._batched_insert(
@@ -448,20 +410,15 @@ class HookQuerySet(models.QuerySet):
448
410
  setattr(obj_without_pk, field.attname, result)
449
411
  obj_without_pk._state.adding = False
450
412
  obj_without_pk._state.db = self.db
451
-
452
- print(f"DEBUG: Successfully bulk created child objects using Django's internal methods")
453
413
 
454
414
  # Step 3: Update original objects with generated PKs and state
455
415
  pk_field_name = child_model._meta.pk.name
456
- print(f"DEBUG: Updating original objects with PK field: {pk_field_name}")
457
416
  for orig_obj, child_obj in zip(batch, all_child_objects):
458
417
  child_pk = getattr(child_obj, pk_field_name)
459
- print(f"DEBUG: Setting {orig_obj.__class__.__name__} PK to {child_pk}")
460
418
  setattr(orig_obj, pk_field_name, child_pk)
461
419
  orig_obj._state.adding = False
462
420
  orig_obj._state.db = self.db
463
421
 
464
- print(f"DEBUG: Completed processing batch")
465
422
  return batch
466
423
 
467
424
  def _create_parent_instance(self, source_obj, parent_model, current_parent):
@@ -510,12 +467,10 @@ class HookQuerySet(models.QuerySet):
510
467
  for parent_model, parent_instance in parent_instances.items():
511
468
  parent_link = child_model._meta.get_ancestor_link(parent_model)
512
469
  if parent_link:
513
- print(f"DEBUG: Parent link: {parent_link.name}, target_field: {parent_link.target_field.name}, attname: {parent_link.target_field.attname}")
514
- print(f"DEBUG: Parent link attname: {parent_link.attname}")
515
- # Set the foreign key value (the ID) to the parent's PK
516
- # Use the parent link field's attname, not the target field's attname
517
- setattr(child_obj, parent_link.attname, parent_instance.pk)
518
- print(f"DEBUG: Set {parent_link.attname} to {parent_instance.pk}")
470
+ # Set both the foreign key value (the ID) and the object reference
471
+ # This follows Django's pattern in _set_pk_val
472
+ setattr(child_obj, parent_link.attname, parent_instance.pk) # Set the foreign key value
473
+ setattr(child_obj, parent_link.name, parent_instance) # Set the object reference
519
474
 
520
475
  # Handle auto_now_add and auto_now fields like Django does
521
476
  for field in child_model._meta.local_fields:
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.1.145"
3
+ version = "0.1.147"
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"