django-bulk-hooks 0.1.146__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.
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/PKG-INFO +1 -1
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/queryset.py +0 -47
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/pyproject.toml +1 -1
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/LICENSE +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/README.md +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/engine.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/models.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/priority.py +0 -0
- {django_bulk_hooks-0.1.146 → django_bulk_hooks-0.1.147}/django_bulk_hooks/registry.py +0 -0
|
@@ -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,14 +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
470
|
# Set both the foreign key value (the ID) and the object reference
|
|
516
471
|
# This follows Django's pattern in _set_pk_val
|
|
517
472
|
setattr(child_obj, parent_link.attname, parent_instance.pk) # Set the foreign key value
|
|
518
473
|
setattr(child_obj, parent_link.name, parent_instance) # Set the object reference
|
|
519
|
-
print(f"DEBUG: Set {parent_link.attname} to {parent_instance.pk}")
|
|
520
|
-
print(f"DEBUG: Set {parent_link.name} to {parent_instance}")
|
|
521
474
|
|
|
522
475
|
# Handle auto_now_add and auto_now fields like Django does
|
|
523
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.
|
|
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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|