django-bulk-hooks 0.1.146__py3-none-any.whl → 0.1.148__py3-none-any.whl
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/queryset.py +18 -47
- {django_bulk_hooks-0.1.146.dist-info → django_bulk_hooks-0.1.148.dist-info}/METADATA +1 -1
- {django_bulk_hooks-0.1.146.dist-info → django_bulk_hooks-0.1.148.dist-info}/RECORD +5 -5
- {django_bulk_hooks-0.1.146.dist-info → django_bulk_hooks-0.1.148.dist-info}/LICENSE +0 -0
- {django_bulk_hooks-0.1.146.dist-info → django_bulk_hooks-0.1.148.dist-info}/WHEEL +0 -0
django_bulk_hooks/queryset.py
CHANGED
|
@@ -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,16 +325,25 @@ 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
|
-
|
|
336
|
-
|
|
328
|
+
# Get bypass_hooks from kwargs
|
|
329
|
+
bypass_hooks = kwargs.get('bypass_hooks', False)
|
|
330
|
+
bypass_validation = kwargs.get('bypass_validation', False)
|
|
331
|
+
|
|
337
332
|
for obj in batch:
|
|
338
333
|
parent_instances = {}
|
|
339
334
|
current_parent = None
|
|
340
335
|
for model_class in inheritance_chain[:-1]:
|
|
341
|
-
print(f"DEBUG: Creating parent instance for {model_class.__name__}")
|
|
342
336
|
parent_obj = self._create_parent_instance(
|
|
343
337
|
obj, model_class, current_parent
|
|
344
338
|
)
|
|
339
|
+
|
|
340
|
+
# Fire parent hooks if not bypassed
|
|
341
|
+
if not bypass_hooks:
|
|
342
|
+
ctx = HookContext(model_class)
|
|
343
|
+
if not bypass_validation:
|
|
344
|
+
engine.run(model_class, VALIDATE_CREATE, [parent_obj], ctx=ctx)
|
|
345
|
+
engine.run(model_class, BEFORE_CREATE, [parent_obj], ctx=ctx)
|
|
346
|
+
|
|
345
347
|
# Use Django's base manager to create the object and get PKs back
|
|
346
348
|
# This bypasses hooks and the MTI exception
|
|
347
349
|
field_values = {
|
|
@@ -349,32 +351,32 @@ class HookQuerySet(models.QuerySet):
|
|
|
349
351
|
for field in model_class._meta.local_fields
|
|
350
352
|
if hasattr(parent_obj, field.name) and getattr(parent_obj, field.name) is not None
|
|
351
353
|
}
|
|
352
|
-
print(f"DEBUG: Creating {model_class.__name__} with field_values: {field_values}")
|
|
353
354
|
created_obj = model_class._base_manager.using(self.db).create(**field_values)
|
|
354
|
-
|
|
355
|
+
|
|
355
356
|
# Update the parent_obj with the created object's PK
|
|
356
357
|
parent_obj.pk = created_obj.pk
|
|
357
358
|
parent_obj._state.adding = False
|
|
358
359
|
parent_obj._state.db = self.db
|
|
360
|
+
|
|
361
|
+
# Fire AFTER_CREATE hooks for parent
|
|
362
|
+
if not bypass_hooks:
|
|
363
|
+
engine.run(model_class, AFTER_CREATE, [parent_obj], ctx=ctx)
|
|
364
|
+
|
|
359
365
|
parent_instances[model_class] = parent_obj
|
|
360
366
|
current_parent = parent_obj
|
|
361
367
|
parent_objects_map[id(obj)] = parent_instances
|
|
362
368
|
|
|
363
369
|
# Step 2: Create all child objects and do single bulk insert into childmost table
|
|
364
370
|
child_model = inheritance_chain[-1]
|
|
365
|
-
print(f"DEBUG: Creating child objects for {child_model.__name__}")
|
|
366
371
|
all_child_objects = []
|
|
367
372
|
for obj in batch:
|
|
368
373
|
child_obj = self._create_child_instance(
|
|
369
374
|
obj, child_model, parent_objects_map.get(id(obj), {})
|
|
370
375
|
)
|
|
371
376
|
all_child_objects.append(child_obj)
|
|
372
|
-
print(f"DEBUG: Created {len(all_child_objects)} child objects")
|
|
373
377
|
|
|
374
378
|
# Step 2.5: Use Django's internal bulk_create infrastructure
|
|
375
379
|
if all_child_objects:
|
|
376
|
-
print(f"DEBUG: Using Django's internal bulk_create infrastructure for {len(all_child_objects)} child objects")
|
|
377
|
-
|
|
378
380
|
# Get the base manager's queryset
|
|
379
381
|
base_qs = child_model._base_manager.using(self.db)
|
|
380
382
|
|
|
@@ -389,38 +391,17 @@ class HookQuerySet(models.QuerySet):
|
|
|
389
391
|
else:
|
|
390
392
|
objs_without_pk.append(obj)
|
|
391
393
|
|
|
392
|
-
print(f"DEBUG: Prepared {len(objs_with_pk)} objects with PK, {len(objs_without_pk)} objects without PK")
|
|
393
|
-
|
|
394
394
|
# Use Django's internal _batched_insert method
|
|
395
395
|
opts = child_model._meta
|
|
396
396
|
# For child models in MTI, we need to include the foreign key to the parent
|
|
397
397
|
# 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
398
|
|
|
400
399
|
# Include all local fields except generated ones
|
|
401
400
|
# We need to include the foreign key to the parent (business_ptr)
|
|
402
401
|
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
402
|
|
|
421
403
|
with transaction.atomic(using=self.db, savepoint=False):
|
|
422
404
|
if objs_with_pk:
|
|
423
|
-
print(f"DEBUG: Inserting {len(objs_with_pk)} objects with PK")
|
|
424
405
|
returned_columns = base_qs._batched_insert(
|
|
425
406
|
objs_with_pk,
|
|
426
407
|
fields,
|
|
@@ -435,7 +416,6 @@ class HookQuerySet(models.QuerySet):
|
|
|
435
416
|
obj_with_pk._state.db = self.db
|
|
436
417
|
|
|
437
418
|
if objs_without_pk:
|
|
438
|
-
print(f"DEBUG: Inserting {len(objs_without_pk)} objects without PK")
|
|
439
419
|
# For objects without PK, we still need to exclude primary key fields
|
|
440
420
|
fields = [f for f in fields if not isinstance(f, AutoField) and not f.primary_key]
|
|
441
421
|
returned_columns = base_qs._batched_insert(
|
|
@@ -448,20 +428,15 @@ class HookQuerySet(models.QuerySet):
|
|
|
448
428
|
setattr(obj_without_pk, field.attname, result)
|
|
449
429
|
obj_without_pk._state.adding = False
|
|
450
430
|
obj_without_pk._state.db = self.db
|
|
451
|
-
|
|
452
|
-
print(f"DEBUG: Successfully bulk created child objects using Django's internal methods")
|
|
453
431
|
|
|
454
432
|
# Step 3: Update original objects with generated PKs and state
|
|
455
433
|
pk_field_name = child_model._meta.pk.name
|
|
456
|
-
print(f"DEBUG: Updating original objects with PK field: {pk_field_name}")
|
|
457
434
|
for orig_obj, child_obj in zip(batch, all_child_objects):
|
|
458
435
|
child_pk = getattr(child_obj, pk_field_name)
|
|
459
|
-
print(f"DEBUG: Setting {orig_obj.__class__.__name__} PK to {child_pk}")
|
|
460
436
|
setattr(orig_obj, pk_field_name, child_pk)
|
|
461
437
|
orig_obj._state.adding = False
|
|
462
438
|
orig_obj._state.db = self.db
|
|
463
439
|
|
|
464
|
-
print(f"DEBUG: Completed processing batch")
|
|
465
440
|
return batch
|
|
466
441
|
|
|
467
442
|
def _create_parent_instance(self, source_obj, parent_model, current_parent):
|
|
@@ -510,14 +485,10 @@ class HookQuerySet(models.QuerySet):
|
|
|
510
485
|
for parent_model, parent_instance in parent_instances.items():
|
|
511
486
|
parent_link = child_model._meta.get_ancestor_link(parent_model)
|
|
512
487
|
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
488
|
# Set both the foreign key value (the ID) and the object reference
|
|
516
489
|
# This follows Django's pattern in _set_pk_val
|
|
517
490
|
setattr(child_obj, parent_link.attname, parent_instance.pk) # Set the foreign key value
|
|
518
491
|
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
492
|
|
|
522
493
|
# Handle auto_now_add and auto_now fields like Django does
|
|
523
494
|
for field in child_model._meta.local_fields:
|
|
@@ -9,9 +9,9 @@ django_bulk_hooks/handler.py,sha256=xZt8iNdYF-ACz-MnKMY0co6scWINU5V5wC1lyDn844k,
|
|
|
9
9
|
django_bulk_hooks/manager.py,sha256=r54ct3S6AcqME2OsX-jPF944CEKcoSIW3qiAx_NwUaw,2801
|
|
10
10
|
django_bulk_hooks/models.py,sha256=7RG7GrOdHXFjGVPV4FPRZVNMIHHW-hMCi6hn9LH_hVI,3331
|
|
11
11
|
django_bulk_hooks/priority.py,sha256=HG_2D35nga68lBCZmSXTcplXrjFoRgZFRDOy4ROKonY,376
|
|
12
|
-
django_bulk_hooks/queryset.py,sha256=
|
|
12
|
+
django_bulk_hooks/queryset.py,sha256=3DOzQ_UJdrngllNskeTrQyxBnFydpS6Vr7Rml9ekrPQ,21914
|
|
13
13
|
django_bulk_hooks/registry.py,sha256=-mQBizJ06nz_tajZBinViKx_uP2Tbc1tIpTEMv7lwKA,705
|
|
14
|
-
django_bulk_hooks-0.1.
|
|
15
|
-
django_bulk_hooks-0.1.
|
|
16
|
-
django_bulk_hooks-0.1.
|
|
17
|
-
django_bulk_hooks-0.1.
|
|
14
|
+
django_bulk_hooks-0.1.148.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
|
|
15
|
+
django_bulk_hooks-0.1.148.dist-info/METADATA,sha256=XN6Io-Ix4rlqmjjjATGrDjLL7CUR41Ljqfsk7FGW6Yc,6951
|
|
16
|
+
django_bulk_hooks-0.1.148.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
17
|
+
django_bulk_hooks-0.1.148.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|