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

@@ -520,9 +520,75 @@ class HookQuerySetMixin:
520
520
  # Fire hooks before DB ops
521
521
  if not bypass_hooks:
522
522
  ctx = HookContext(model_cls, bypass_hooks=False) # Pass bypass_hooks
523
- if not bypass_validation:
524
- engine.run(model_cls, VALIDATE_CREATE, objs, ctx=ctx)
525
- engine.run(model_cls, BEFORE_CREATE, objs, ctx=ctx)
523
+
524
+ if update_conflicts and unique_fields:
525
+ # For upsert operations, we need to determine which records will be created vs updated
526
+ # Check which records already exist in the database based on unique fields
527
+ existing_records = []
528
+ new_records = []
529
+
530
+ # Build a filter to check which records already exist
531
+ unique_values = []
532
+ for obj in objs:
533
+ unique_value = {}
534
+ for field_name in unique_fields:
535
+ if hasattr(obj, field_name):
536
+ unique_value[field_name] = getattr(obj, field_name)
537
+ if unique_value:
538
+ unique_values.append(unique_value)
539
+
540
+ if unique_values:
541
+ # Query the database to see which records already exist
542
+ from django.db.models import Q
543
+ existing_filters = Q()
544
+ for unique_value in unique_values:
545
+ filter_kwargs = {}
546
+ for field_name, value in unique_value.items():
547
+ filter_kwargs[field_name] = value
548
+ existing_filters |= Q(**filter_kwargs)
549
+
550
+ existing_pks = set(
551
+ model_cls.objects.filter(existing_filters).values_list('pk', flat=True)
552
+ )
553
+
554
+ # Separate records based on whether they already exist
555
+ for obj in objs:
556
+ obj_unique_value = {}
557
+ for field_name in unique_fields:
558
+ if hasattr(obj, field_name):
559
+ obj_unique_value[field_name] = getattr(obj, field_name)
560
+
561
+ # Check if this record already exists
562
+ if obj_unique_value:
563
+ existing_q = Q()
564
+ for field_name, value in obj_unique_value.items():
565
+ existing_q &= Q(**{field_name: value})
566
+
567
+ if model_cls.objects.filter(existing_q).exists():
568
+ existing_records.append(obj)
569
+ else:
570
+ new_records.append(obj)
571
+ else:
572
+ # If we can't determine uniqueness, treat as new
573
+ new_records.append(obj)
574
+ else:
575
+ # If no unique fields, treat all as new
576
+ new_records = objs
577
+
578
+ # Run validation hooks on all records
579
+ if not bypass_validation:
580
+ engine.run(model_cls, VALIDATE_CREATE, objs, ctx=ctx)
581
+
582
+ # Run appropriate BEFORE hooks based on what will happen
583
+ if new_records:
584
+ engine.run(model_cls, BEFORE_CREATE, new_records, ctx=ctx)
585
+ if existing_records:
586
+ engine.run(model_cls, BEFORE_UPDATE, existing_records, ctx=ctx)
587
+ else:
588
+ # For regular create operations, run create hooks before DB ops
589
+ if not bypass_validation:
590
+ engine.run(model_cls, VALIDATE_CREATE, objs, ctx=ctx)
591
+ engine.run(model_cls, BEFORE_CREATE, objs, ctx=ctx)
526
592
  else:
527
593
  ctx = HookContext(model_cls, bypass_hooks=True) # Pass bypass_hooks
528
594
  logger.debug("bulk_create bypassed hooks")
@@ -557,9 +623,70 @@ class HookQuerySetMixin:
557
623
  unique_fields=unique_fields,
558
624
  )
559
625
 
560
- # Fire AFTER_CREATE hooks
626
+ # Fire AFTER hooks
561
627
  if not bypass_hooks:
562
- engine.run(model_cls, AFTER_CREATE, objs, ctx=ctx)
628
+ if update_conflicts and unique_fields:
629
+ # For upsert operations, we need to determine which records were actually created vs updated
630
+ # Use the same logic as before to separate records
631
+ existing_records = []
632
+ new_records = []
633
+
634
+ # Build a filter to check which records already exist
635
+ unique_values = []
636
+ for obj in objs:
637
+ unique_value = {}
638
+ for field_name in unique_fields:
639
+ if hasattr(obj, field_name):
640
+ unique_value[field_name] = getattr(obj, field_name)
641
+ if unique_value:
642
+ unique_values.append(unique_value)
643
+
644
+ if unique_values:
645
+ # Query the database to see which records already exist
646
+ from django.db.models import Q
647
+ existing_filters = Q()
648
+ for unique_value in unique_values:
649
+ filter_kwargs = {}
650
+ for field_name, value in unique_value.items():
651
+ filter_kwargs[field_name] = value
652
+ existing_filters |= Q(**filter_kwargs)
653
+
654
+ existing_pks = set(
655
+ model_cls.objects.filter(existing_filters).values_list('pk', flat=True)
656
+ )
657
+
658
+ # Separate records based on whether they already exist
659
+ for obj in objs:
660
+ obj_unique_value = {}
661
+ for field_name in unique_fields:
662
+ if hasattr(obj, field_name):
663
+ obj_unique_value[field_name] = getattr(obj, field_name)
664
+
665
+ # Check if this record already exists
666
+ if obj_unique_value:
667
+ existing_q = Q()
668
+ for field_name, value in obj_unique_value.items():
669
+ existing_q &= Q(**{field_name: value})
670
+
671
+ if model_cls.objects.filter(existing_q).exists():
672
+ existing_records.append(obj)
673
+ else:
674
+ new_records.append(obj)
675
+ else:
676
+ # If we can't determine uniqueness, treat as new
677
+ new_records.append(obj)
678
+ else:
679
+ # If no unique fields, treat all as new
680
+ new_records = objs
681
+
682
+ # Run appropriate AFTER hooks based on what actually happened
683
+ if new_records:
684
+ engine.run(model_cls, AFTER_CREATE, new_records, ctx=ctx)
685
+ if existing_records:
686
+ engine.run(model_cls, AFTER_UPDATE, existing_records, ctx=ctx)
687
+ else:
688
+ # For regular create operations, run create hooks after DB ops
689
+ engine.run(model_cls, AFTER_CREATE, objs, ctx=ctx)
563
690
 
564
691
  return result
565
692
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.251
3
+ Version: 0.1.252
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
@@ -9,9 +9,9 @@ django_bulk_hooks/handler.py,sha256=Bx-W6yyiciKMyy-BRxUt3CmRPCrX9_LhQgU-5LaJTjg,
9
9
  django_bulk_hooks/manager.py,sha256=nfWiwU5-yAoxdnQsUMohxtyCpkV0MBv6X3wmipr9eQY,3697
10
10
  django_bulk_hooks/models.py,sha256=WtSfc4GBOG_oOt8n37cVvid0MtFIGze9JYKSixil2y0,4370
11
11
  django_bulk_hooks/priority.py,sha256=HG_2D35nga68lBCZmSXTcplXrjFoRgZFRDOy4ROKonY,376
12
- django_bulk_hooks/queryset.py,sha256=qwmxR5fwNZhJYv6I2PF-vQBve6WAaVff_5uh5c2fvZ4,54117
12
+ django_bulk_hooks/queryset.py,sha256=whv6QunaxRhos0nBlx600mKeleovjdv3XdeMSULh7n8,60739
13
13
  django_bulk_hooks/registry.py,sha256=GRUTGVQEO2sdkC9OaZ9Q3U7mM-3Ix83uTyvrlTtpatw,1317
14
- django_bulk_hooks-0.1.251.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
15
- django_bulk_hooks-0.1.251.dist-info/METADATA,sha256=7CITFSsuic7whOclVWFarrkE_nLRLC0bV4FMwrce5aI,9061
16
- django_bulk_hooks-0.1.251.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
17
- django_bulk_hooks-0.1.251.dist-info/RECORD,,
14
+ django_bulk_hooks-0.1.252.dist-info/LICENSE,sha256=dguKIcbDGeZD-vXWdLyErPUALYOvtX_fO4Zjhq481uk,1088
15
+ django_bulk_hooks-0.1.252.dist-info/METADATA,sha256=xg9nPjRhZJPXem1plWls94mzENbAAoNiWI43J931rpE,9061
16
+ django_bulk_hooks-0.1.252.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
17
+ django_bulk_hooks-0.1.252.dist-info/RECORD,,