django-bulk-hooks 0.1.279__tar.gz → 0.1.281__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.

Files changed (17) hide show
  1. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/PKG-INFO +1 -1
  2. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/queryset.py +83 -10
  3. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/pyproject.toml +1 -1
  4. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/LICENSE +0 -0
  5. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/README.md +0 -0
  6. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/__init__.py +0 -0
  7. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/conditions.py +0 -0
  8. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/constants.py +0 -0
  9. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/context.py +0 -0
  10. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/decorators.py +0 -0
  11. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/engine.py +0 -0
  12. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/enums.py +0 -0
  13. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/handler.py +0 -0
  14. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/manager.py +0 -0
  15. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/models.py +0 -0
  16. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/priority.py +0 -0
  17. {django_bulk_hooks-0.1.279 → django_bulk_hooks-0.1.281}/django_bulk_hooks/registry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-bulk-hooks
3
- Version: 0.1.279
3
+ Version: 0.1.281
4
4
  Summary: Hook-style hooks for Django bulk operations like bulk_create and bulk_update.
5
5
  Home-page: https://github.com/AugendLimited/django-bulk-hooks
6
6
  License: MIT
@@ -1722,9 +1722,12 @@ class HookQuerySetMixin:
1722
1722
  parent_update_fields = kwargs.get("update_fields")
1723
1723
  if parent_update_fields:
1724
1724
  # Only include fields that exist in the parent model
1725
- parent_model_fields = {field.name for field in model_class._meta.local_fields}
1725
+ parent_model_fields = {
1726
+ field.name for field in model_class._meta.local_fields
1727
+ }
1726
1728
  filtered_update_fields = [
1727
- field for field in parent_update_fields
1729
+ field
1730
+ for field in parent_update_fields
1728
1731
  if field in parent_model_fields
1729
1732
  ]
1730
1733
  parent_obj.save(update_fields=filtered_update_fields)
@@ -1770,16 +1773,47 @@ class HookQuerySetMixin:
1770
1773
  current_parent = parent_obj
1771
1774
  parent_objects_map[id(obj)] = parent_instances
1772
1775
 
1773
- # Step 2: Create all child objects and do single bulk insert into childmost table
1776
+ # Step 2: Handle child objects - create new ones and update existing ones
1774
1777
  child_model = inheritance_chain[-1]
1775
1778
  all_child_objects = []
1779
+ existing_child_objects = []
1780
+
1776
1781
  for obj in batch:
1777
- child_obj = self._create_child_instance(
1778
- obj, child_model, parent_objects_map.get(id(obj), {})
1779
- )
1780
- all_child_objects.append(child_obj)
1782
+ is_existing_record = obj in existing_records_list
1781
1783
 
1782
- # Step 2.5: Use Django's internal bulk_create infrastructure
1784
+ if is_existing_record:
1785
+ # For existing records, update the child object
1786
+ child_obj = self._create_child_instance(
1787
+ obj, child_model, parent_objects_map.get(id(obj), {})
1788
+ )
1789
+ existing_child_objects.append(child_obj)
1790
+ else:
1791
+ # For new records, create the child object
1792
+ child_obj = self._create_child_instance(
1793
+ obj, child_model, parent_objects_map.get(id(obj), {})
1794
+ )
1795
+ all_child_objects.append(child_obj)
1796
+
1797
+ # Step 2.5: Update existing child objects
1798
+ if existing_child_objects:
1799
+ for child_obj in existing_child_objects:
1800
+ # Filter update_fields to only include fields that exist in the child model
1801
+ child_update_fields = kwargs.get("update_fields")
1802
+ if child_update_fields:
1803
+ # Only include fields that exist in the child model
1804
+ child_model_fields = {
1805
+ field.name for field in child_model._meta.local_fields
1806
+ }
1807
+ filtered_child_update_fields = [
1808
+ field
1809
+ for field in child_update_fields
1810
+ if field in child_model_fields
1811
+ ]
1812
+ child_obj.save(update_fields=filtered_child_update_fields)
1813
+ else:
1814
+ child_obj.save()
1815
+
1816
+ # Step 2.6: Use Django's internal bulk_create infrastructure for new child objects
1783
1817
  if all_child_objects:
1784
1818
  # Get the base manager's queryset
1785
1819
  base_qs = child_model._base_manager.using(self.db)
@@ -1841,12 +1875,21 @@ class HookQuerySetMixin:
1841
1875
 
1842
1876
  # Step 3: Update original objects with generated PKs and state
1843
1877
  pk_field_name = child_model._meta.pk.name
1878
+
1879
+ # Handle new objects
1844
1880
  for orig_obj, child_obj in zip(batch, all_child_objects):
1845
1881
  child_pk = getattr(child_obj, pk_field_name)
1846
1882
  setattr(orig_obj, pk_field_name, child_pk)
1847
1883
  orig_obj._state.adding = False
1848
1884
  orig_obj._state.db = self.db
1849
1885
 
1886
+ # Handle existing objects (they already have PKs, just update state)
1887
+ for orig_obj in batch:
1888
+ is_existing_record = orig_obj in existing_records_list
1889
+ if is_existing_record:
1890
+ orig_obj._state.adding = False
1891
+ orig_obj._state.db = self.db
1892
+
1850
1893
  return batch
1851
1894
 
1852
1895
  def _create_parent_instance(self, source_obj, parent_model, current_parent):
@@ -1856,7 +1899,22 @@ class HookQuerySetMixin:
1856
1899
  if hasattr(source_obj, field.name):
1857
1900
  value = getattr(source_obj, field.name, None)
1858
1901
  if value is not None:
1859
- setattr(parent_obj, field.name, value)
1902
+ # Handle foreign key fields properly
1903
+ if (
1904
+ field.is_relation
1905
+ and not field.many_to_many
1906
+ and not field.one_to_many
1907
+ ):
1908
+ # For foreign key fields, extract the ID if we have a model instance
1909
+ if hasattr(value, "pk") and value.pk is not None:
1910
+ # Set the foreign key ID field (e.g., loan_account_id)
1911
+ setattr(parent_obj, field.attname, value.pk)
1912
+ else:
1913
+ # If it's already an ID or None, use it as-is
1914
+ setattr(parent_obj, field.attname, value)
1915
+ else:
1916
+ # For non-relation fields, copy the value directly
1917
+ setattr(parent_obj, field.name, value)
1860
1918
  if current_parent is not None:
1861
1919
  for field in parent_model._meta.local_fields:
1862
1920
  if (
@@ -1889,7 +1947,22 @@ class HookQuerySetMixin:
1889
1947
  if hasattr(source_obj, field.name):
1890
1948
  value = getattr(source_obj, field.name, None)
1891
1949
  if value is not None:
1892
- setattr(child_obj, field.name, value)
1950
+ # Handle foreign key fields properly
1951
+ if (
1952
+ field.is_relation
1953
+ and not field.many_to_many
1954
+ and not field.one_to_many
1955
+ ):
1956
+ # For foreign key fields, extract the ID if we have a model instance
1957
+ if hasattr(value, "pk") and value.pk is not None:
1958
+ # Set the foreign key ID field (e.g., loan_account_id)
1959
+ setattr(child_obj, field.attname, value.pk)
1960
+ else:
1961
+ # If it's already an ID or None, use it as-is
1962
+ setattr(child_obj, field.attname, value)
1963
+ else:
1964
+ # For non-relation fields, copy the value directly
1965
+ setattr(child_obj, field.name, value)
1893
1966
 
1894
1967
  # Set parent links for MTI
1895
1968
  for parent_model, parent_instance in parent_instances.items():
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-bulk-hooks"
3
- version = "0.1.279"
3
+ version = "0.1.281"
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"