django-bulk-hooks 0.1.256__tar.gz → 0.1.258__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.256 → django_bulk_hooks-0.1.258}/PKG-INFO +1 -1
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/queryset.py +41 -14
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/pyproject.toml +1 -1
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/LICENSE +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/README.md +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/engine.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/models.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/priority.py +0 -0
- {django_bulk_hooks-0.1.256 → django_bulk_hooks-0.1.258}/django_bulk_hooks/registry.py +0 -0
|
@@ -482,6 +482,11 @@ class HookQuerySetMixin:
|
|
|
482
482
|
passed through to the correct logic. For MTI, only a subset of options may be supported.
|
|
483
483
|
"""
|
|
484
484
|
model_cls = self.model
|
|
485
|
+
|
|
486
|
+
print(f"DEBUG: bulk_create called for {model_cls.__name__} with {len(objs)} objects")
|
|
487
|
+
print(f"DEBUG: update_conflicts={update_conflicts}, unique_fields={unique_fields}, update_fields={update_fields}")
|
|
488
|
+
logger.debug(f"bulk_create called for {model_cls.__name__} with {len(objs)} objects")
|
|
489
|
+
logger.debug(f"update_conflicts={update_conflicts}, unique_fields={unique_fields}, update_fields={update_fields}")
|
|
485
490
|
|
|
486
491
|
# When you bulk insert you don't get the primary keys back (if it's an
|
|
487
492
|
# autoincrement, except if can_return_rows_from_bulk_insert=True), so
|
|
@@ -624,6 +629,20 @@ class HookQuerySetMixin:
|
|
|
624
629
|
# Preserve the original updated_at timestamp
|
|
625
630
|
setattr(obj, field.name, getattr(db_record, field.name))
|
|
626
631
|
|
|
632
|
+
# CRITICAL: For existing records, we need to set updated_at to current time
|
|
633
|
+
# since they are being updated, not just preserved
|
|
634
|
+
if existing_records:
|
|
635
|
+
from django.utils import timezone
|
|
636
|
+
current_time = timezone.now()
|
|
637
|
+
print(f"DEBUG: Setting updated_at to current time for {len(existing_records)} existing records")
|
|
638
|
+
logger.debug(f"Setting updated_at to current time for {len(existing_records)} existing records")
|
|
639
|
+
for obj in existing_records:
|
|
640
|
+
for field in model_cls._meta.local_fields:
|
|
641
|
+
if hasattr(field, "auto_now") and field.auto_now:
|
|
642
|
+
setattr(obj, field.name, current_time)
|
|
643
|
+
print(f"DEBUG: Set {field.name} to {current_time} for existing record {obj.pk}")
|
|
644
|
+
logger.debug(f"Set {field.name} to {current_time} for existing record {obj.pk}")
|
|
645
|
+
|
|
627
646
|
# CRITICAL: Exclude auto_now fields from update_fields for existing records
|
|
628
647
|
# This prevents Django from including them in the ON CONFLICT DO UPDATE clause
|
|
629
648
|
if existing_records and update_fields:
|
|
@@ -817,6 +836,7 @@ class HookQuerySetMixin:
|
|
|
817
836
|
logger.debug(
|
|
818
837
|
f"bulk_update {model_cls.__name__} bypass_hooks={bypass_hooks} objs={len(objs)} fields={fields}"
|
|
819
838
|
)
|
|
839
|
+
print(f"DEBUG: bulk_update {model_cls.__name__} bypass_hooks={bypass_hooks} objs={len(objs)} fields={fields}")
|
|
820
840
|
|
|
821
841
|
# Check for MTI
|
|
822
842
|
is_mti = False
|
|
@@ -846,28 +866,34 @@ class HookQuerySetMixin:
|
|
|
846
866
|
# Don't include auto_now_add fields (like created_at) as they should only be set on creation
|
|
847
867
|
if hasattr(field, "auto_now") and field.auto_now:
|
|
848
868
|
logger.debug(f"Found auto_now field: {field.name}")
|
|
869
|
+
print(f"DEBUG: Found auto_now field: {field.name}")
|
|
849
870
|
if field.name not in fields_set and field.name not in pk_fields:
|
|
850
871
|
fields_set.add(field.name)
|
|
851
872
|
if field.name != field.attname:
|
|
852
873
|
fields_set.add(field.attname)
|
|
853
874
|
auto_now_fields.append(field.name)
|
|
854
875
|
logger.debug(f"Added auto_now field {field.name} to fields list")
|
|
876
|
+
print(f"DEBUG: Added auto_now field {field.name} to fields list")
|
|
855
877
|
else:
|
|
856
878
|
logger.debug(f"Auto_now field {field.name} already in fields list or is PK")
|
|
879
|
+
print(f"DEBUG: Auto_now field {field.name} already in fields list or is PK")
|
|
857
880
|
elif hasattr(field, "auto_now_add") and field.auto_now_add:
|
|
858
881
|
logger.debug(f"Found auto_now_add field: {field.name} (skipping)")
|
|
859
882
|
|
|
860
883
|
logger.debug(f"Auto_now fields detected: {auto_now_fields}")
|
|
884
|
+
print(f"DEBUG: Auto_now fields detected: {auto_now_fields}")
|
|
861
885
|
fields = list(fields_set)
|
|
862
886
|
|
|
863
887
|
# Set auto_now field values to current timestamp
|
|
864
888
|
if auto_now_fields:
|
|
865
889
|
from django.utils import timezone
|
|
866
890
|
current_time = timezone.now()
|
|
891
|
+
print(f"DEBUG: Setting auto_now fields {auto_now_fields} to current time: {current_time}")
|
|
867
892
|
logger.debug(f"Setting auto_now fields {auto_now_fields} to current time: {current_time}")
|
|
868
893
|
for obj in objs:
|
|
869
894
|
for field_name in auto_now_fields:
|
|
870
895
|
setattr(obj, field_name, current_time)
|
|
896
|
+
print(f"DEBUG: Set {field_name} to {current_time} for object {obj.pk}")
|
|
871
897
|
|
|
872
898
|
# Handle MTI models differently
|
|
873
899
|
if is_mti:
|
|
@@ -880,20 +906,21 @@ class HookQuerySetMixin:
|
|
|
880
906
|
if k not in ["bypass_hooks", "bypass_validation"]
|
|
881
907
|
}
|
|
882
908
|
logger.debug("Calling Django bulk_update")
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
909
|
+
print("DEBUG: Calling Django bulk_update")
|
|
910
|
+
# Build a per-object concrete value map to avoid leaking expressions into hooks
|
|
911
|
+
value_map = {}
|
|
912
|
+
logger.debug(f"Building value map for {len(objs)} objects with fields: {fields}")
|
|
913
|
+
for obj in objs:
|
|
914
|
+
if obj.pk is None:
|
|
915
|
+
continue
|
|
916
|
+
field_values = {}
|
|
917
|
+
for field_name in fields:
|
|
918
|
+
# Capture raw values assigned on the object (not expressions)
|
|
919
|
+
field_values[field_name] = getattr(obj, field_name)
|
|
920
|
+
if field_name in auto_now_fields:
|
|
921
|
+
logger.debug(f"Object {obj.pk} {field_name}: {field_values[field_name]}")
|
|
922
|
+
if field_values:
|
|
923
|
+
value_map[obj.pk] = field_values
|
|
897
924
|
|
|
898
925
|
# Make the value map available to the subsequent update() call
|
|
899
926
|
if value_map:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "django-bulk-hooks"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.258"
|
|
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
|