django-bulk-hooks 0.2.52__py3-none-any.whl → 0.2.54__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.

@@ -261,57 +261,46 @@ class BulkExecutor:
261
261
  parent_instances_map[orig_obj_id] = {}
262
262
  parent_instances_map[orig_obj_id][parent_level.model_class] = parent_obj
263
263
 
264
- # Step 2: Add parent links to child objects and set PKs for existing records
264
+ # Step 2: Add parent links to child objects and set PKs appropriately
265
265
  for child_obj, orig_obj in zip(plan.child_objects, plan.original_objects):
266
266
  parent_instances = parent_instances_map.get(id(orig_obj), {})
267
267
 
268
- # Set parent links
268
+ # Set parent links and PKs for all objects (since in MTI, child PK = parent PK)
269
269
  for parent_model, parent_instance in parent_instances.items():
270
270
  parent_link = plan.child_model._meta.get_ancestor_link(parent_model)
271
271
  if parent_link:
272
- setattr(child_obj, parent_link.attname, parent_instance.pk)
272
+ parent_pk = parent_instance.pk
273
+ setattr(child_obj, parent_link.attname, parent_pk)
273
274
  setattr(child_obj, parent_link.name, parent_instance)
274
- # IMPORTANT: Don't set the child's PK here - it should only get PK after insertion
275
- # The parent link field (hookmodel_ptr) is NOT the same as the child's PK
275
+ # In MTI, the child PK IS the parent link
276
+ child_obj.pk = parent_pk
277
+ child_obj.id = parent_pk
276
278
  else:
277
279
  logger.warning(f"No parent link found for {parent_model} in {plan.child_model}")
278
280
 
279
- # For existing records in upsert, ensure PK is set on child object
280
- if id(orig_obj) in plan.existing_record_ids:
281
- pk_value = getattr(orig_obj, "pk", None)
282
- if pk_value:
283
- child_obj.pk = pk_value
284
- child_obj.id = pk_value
285
- else:
286
- # If no PK on original object, this is a new record, don't set PK
287
- logger.info(f"New record {orig_obj} - not setting PK on child object")
288
-
289
281
  # Step 3: Handle child objects
290
282
  # Note: We can't use bulk_create on child MTI models, so we use _batched_insert for new records
291
283
  # and bulk_update for existing records
292
284
  base_qs = BaseQuerySet(model=plan.child_model, using=self.queryset.db)
293
-
294
- # For MTI child objects, we need to handle them differently
295
- # In MTI, child objects get PKs from parent links, but we need to distinguish
296
- # between truly new records and existing records for upsert operations
285
+
286
+ # For MTI child objects, we need to distinguish between truly new records and existing records for upsert operations
297
287
  objs_without_pk, objs_with_pk = [], []
298
-
288
+
299
289
  # Check which CHILD records actually exist in the child table
300
- # This is separate from checking parent existence
301
290
  if plan.update_conflicts:
302
- # Query the CHILD table to see which child records exist
303
- parent_pks = []
291
+ # For upsert, check which child records exist based on the parent PKs
292
+ parent_pks_to_check = []
304
293
  for child_obj in plan.child_objects:
305
294
  child_pk = getattr(child_obj, plan.child_model._meta.pk.attname, None)
306
295
  if child_pk:
307
- parent_pks.append(child_pk)
308
-
296
+ parent_pks_to_check.append(child_pk)
297
+
309
298
  existing_child_pks = set()
310
- if parent_pks:
299
+ if parent_pks_to_check:
311
300
  existing_child_pks = set(
312
- base_qs.filter(pk__in=parent_pks).values_list('pk', flat=True)
301
+ base_qs.filter(pk__in=parent_pks_to_check).values_list('pk', flat=True)
313
302
  )
314
-
303
+
315
304
  # Split based on whether child record exists
316
305
  for child_obj in plan.child_objects:
317
306
  child_pk = getattr(child_obj, plan.child_model._meta.pk.attname, None)
@@ -406,7 +406,12 @@ class MTIHandler:
406
406
  """
407
407
  child_obj = child_model()
408
408
 
409
- # Copy field values (excluding AutoField and parent links)
409
+ # Copy field values (excluding AutoField, parent links, and inherited fields)
410
+ # In MTI, child objects should only have values for fields defined directly on the child model
411
+ parent_fields = set()
412
+ for parent_model in child_model._meta.parents.keys():
413
+ parent_fields.update(f.name for f in parent_model._meta.local_fields)
414
+
410
415
  for field in child_model._meta.local_fields:
411
416
  if isinstance(field, AutoField):
412
417
  continue
@@ -417,6 +422,10 @@ class MTIHandler:
417
422
  if child_model._meta.get_ancestor_link(field.related_model) == field:
418
423
  continue
419
424
 
425
+ # Skip inherited fields - these belong to parent models
426
+ if field.name in parent_fields:
427
+ continue
428
+
420
429
  if hasattr(source_obj, field.name):
421
430
  # Use centralized field value extraction for consistent FK handling
422
431
  value = get_field_value_for_db(source_obj, field.name, source_obj.__class__)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-bulk-hooks
3
- Version: 0.2.52
3
+ Version: 0.2.54
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
@@ -13,15 +13,15 @@ django_bulk_hooks/manager.py,sha256=3mFzB0ZzHHeXWdKGObZD_H0NlskHJc8uYBF69KKdAXU,
13
13
  django_bulk_hooks/models.py,sha256=4Vvi2LiGP0g4j08a5liqBROfsO8Wd_ermBoyjKwfrPU,2512
14
14
  django_bulk_hooks/operations/__init__.py,sha256=BtJYjmRhe_sScivLsniDaZmBkm0ZLvcmzXFKL7QY2Xg,550
15
15
  django_bulk_hooks/operations/analyzer.py,sha256=wAG8sAG9NwfwNqG9z81VfGR7AANDzRmMGE_o82MWji4,10689
16
- django_bulk_hooks/operations/bulk_executor.py,sha256=F_nXtqB2ZRuAEZtSzqtKedqH_TDkNQDPLVmVUT8jsPQ,24794
16
+ django_bulk_hooks/operations/bulk_executor.py,sha256=tMbcwQSN8xNoKL7-KC8m-XhGyqwaAtAQ5CAm3PYHl_Q,24122
17
17
  django_bulk_hooks/operations/coordinator.py,sha256=iGavJLqe3eYRqFay8cMn6muwyRYzQo-HFGphsS5hL6g,30799
18
18
  django_bulk_hooks/operations/field_utils.py,sha256=Tvr5bcZLG8imH-r2S85oui1Cbw6hGv3VtuIMn4OvsU4,2895
19
- django_bulk_hooks/operations/mti_handler.py,sha256=Ro80PGrgm9O9wWuFwhiarcOqLlU95iCOtuvaDIcshQU,20648
19
+ django_bulk_hooks/operations/mti_handler.py,sha256=r6F49-6tHbCeu2DFj6PX_7iU4lv6icbNBI8u-v1Fj9U,21092
20
20
  django_bulk_hooks/operations/mti_plans.py,sha256=7STQ2oA2ZT8cEG3-t-6xciRAdf7OeSf0gRLXR_BRG-Q,3363
21
21
  django_bulk_hooks/operations/record_classifier.py,sha256=kqML4aO11X9K3SSJ5DUlUukwI172j_Tk12Kr77ee8q8,7065
22
22
  django_bulk_hooks/queryset.py,sha256=aQitlbexcVnmeAdc0jtO3hci39p4QEu4srQPEzozy5s,5546
23
23
  django_bulk_hooks/registry.py,sha256=uum5jhGI3TPaoiXuA1MdBdu4gbE3rQGGwQ5YDjiMcjk,7949
24
- django_bulk_hooks-0.2.52.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
25
- django_bulk_hooks-0.2.52.dist-info/METADATA,sha256=VijPFOPGvpd1c6xb3W4WEcjCN6RJP4ASCi_2wJ1U660,9265
26
- django_bulk_hooks-0.2.52.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
- django_bulk_hooks-0.2.52.dist-info/RECORD,,
24
+ django_bulk_hooks-0.2.54.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
25
+ django_bulk_hooks-0.2.54.dist-info/METADATA,sha256=ClVI63n_CscKcG0C_7B9rxCCgN4WnDoO5Rl-kWs0FhM,9265
26
+ django_bulk_hooks-0.2.54.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
+ django_bulk_hooks-0.2.54.dist-info/RECORD,,