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

@@ -306,6 +306,14 @@ class MTIHandler:
306
306
  if not filtered_updates and normalized_unique:
307
307
  filtered_updates = [normalized_unique[0]]
308
308
 
309
+ # CRITICAL FIX: Always include auto_now fields in updates to ensure timestamps are updated.
310
+ # During MTI upsert, parent tables need auto_now fields updated even when only child fields change.
311
+ # This ensures parent-level timestamps (e.g., updated_at) refresh correctly on upsert.
312
+ auto_now_fields = self._get_auto_now_fields_for_model(model_class, model_fields_by_name)
313
+ if auto_now_fields:
314
+ # Convert to set to avoid duplicates, then back to list for consistency
315
+ filtered_updates = list(set(filtered_updates) | set(auto_now_fields))
316
+
309
317
  # Only enable upsert if we have fields to update (real or dummy)
310
318
  if filtered_updates:
311
319
  level_update_conflicts = True
@@ -334,6 +342,14 @@ class MTIHandler:
334
342
  ]
335
343
  level_update_fields = available_fields[:1] if available_fields else [pk_field.name]
336
344
 
345
+ # CRITICAL FIX: Include auto_now fields in update_fields to ensure timestamps are updated.
346
+ # During MTI upsert, parent tables need auto_now fields updated even when using dummy fields.
347
+ # This ensures parent-level timestamps (e.g., updated_at) refresh correctly on upsert.
348
+ auto_now_fields = self._get_auto_now_fields_for_model(model_class, model_fields_by_name)
349
+ if auto_now_fields:
350
+ # Convert to set to avoid duplicates, then back to list for consistency
351
+ level_update_fields = list(set(level_update_fields) | set(auto_now_fields))
352
+
337
353
  # Create parent level
338
354
  parent_level = ParentLevel(
339
355
  model_class=model_class,
@@ -347,6 +363,29 @@ class MTIHandler:
347
363
 
348
364
  return parent_levels
349
365
 
366
+ def _get_auto_now_fields_for_model(self, model_class, model_fields_by_name):
367
+ """
368
+ Get auto_now (not auto_now_add) fields for a specific model.
369
+
370
+ Only includes fields that exist in model_fields_by_name to ensure
371
+ they're valid local fields for this model level.
372
+
373
+ Args:
374
+ model_class: Model class to get fields for
375
+ model_fields_by_name: Dict of valid field names for this model level
376
+
377
+ Returns:
378
+ List of auto_now field names (excluding auto_now_add)
379
+ """
380
+ auto_now_fields = []
381
+ for field in model_class._meta.local_fields:
382
+ # Only include auto_now (not auto_now_add) since auto_now_add should only be set on creation
383
+ if getattr(field, "auto_now", False) and not getattr(field, "auto_now_add", False):
384
+ # Double-check field exists in model_fields_by_name for safety
385
+ if field.name in model_fields_by_name:
386
+ auto_now_fields.append(field.name)
387
+ return auto_now_fields
388
+
350
389
  def _has_matching_constraint(self, model_class, normalized_unique):
351
390
  """Check if model has a unique constraint matching the given fields."""
352
391
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-bulk-hooks
3
- Version: 0.2.57
3
+ Version: 0.2.58
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
@@ -16,12 +16,12 @@ django_bulk_hooks/operations/analyzer.py,sha256=wAG8sAG9NwfwNqG9z81VfGR7AANDzRmM
16
16
  django_bulk_hooks/operations/bulk_executor.py,sha256=Y-wkvuV_X-SZmI965JVrrtwbzPZVggUfy8mR1pzP9d0,27048
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=MMDxuE6jzwkhMwVE-6qJUdp4MNKgAIFPMjwdN_umrqs,23503
19
+ django_bulk_hooks/operations/mti_handler.py,sha256=173jghcxCE5UEZxM1QJRS-lWg0-KJxCQCbWHVKppIEM,26000
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.57.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
25
- django_bulk_hooks-0.2.57.dist-info/METADATA,sha256=SWZOMPOgiBDCLuSxHX9xTeJMqcd3CgvDZP-JuoY4wRs,9265
26
- django_bulk_hooks-0.2.57.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
- django_bulk_hooks-0.2.57.dist-info/RECORD,,
24
+ django_bulk_hooks-0.2.58.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
25
+ django_bulk_hooks-0.2.58.dist-info/METADATA,sha256=kVna-_dN9xVNaMMZHZUzm-Ab4IjhVzA1L8XXPms5T7o,9265
26
+ django_bulk_hooks-0.2.58.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
27
+ django_bulk_hooks-0.2.58.dist-info/RECORD,,