From 127bae291b86dd5e2573b49dc1b5690d3e298c70 Mon Sep 17 00:00:00 2001 From: serbanPricop Date: Mon, 14 Oct 2024 17:45:52 +0300 Subject: [PATCH 1/5] feat(entity): optimize entity save method and add bulk save functionality - Add `commit` parameter to `Entity.save()` method - Implement `save_bulk()` method for efficient bulk creation of EAV values - Modify `save()` method to collect values and use `save_bulk()` when commit is True - Improve performance by reducing database queries during save operations --- eav/models/entity.py | 55 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/eav/models/entity.py b/eav/models/entity.py index c57ac4af..357e8f3c 100644 --- a/eav/models/entity.py +++ b/eav/models/entity.py @@ -99,9 +99,11 @@ def _getattr(self, attribute_slug): """ return self.__dict__[attribute_slug] - def save(self): + def save(self, commit=True): """Saves all the EAV values that have been set on this entity.""" - for attribute in self.get_all_attributes(): + values = {} + attributes = self.get_all_attributes() + for attribute in attributes: if self._hasattr(attribute.slug): attribute_value = self._getattr(attribute.slug) if ( @@ -113,7 +115,10 @@ def save(self): and attribute_value is not None ): attribute_value = EnumValue.objects.get(value=attribute_value) - attribute.save_value(self.instance, attribute_value) + if commit: + attribute.save_value(self.instance, attribute_value) + values[attribute.slug] = attribute_value + self.save_bulk(values, attributes) def validate_attributes(self): """ @@ -200,6 +205,50 @@ def __iter__(self): """ return iter(self.get_values()) + def save_bulk( + self, + eav_values, + attributes, + ): + """ + Prepare a list of EAV Value objects for bulk creation. + + This method takes a dictionary of EAV attribute values and a list of Attribute + objects, and returns a list of Value objects that can be bulk created to update + the EAV data for the current Entity instance. + + Args: + eav_values: A dictionary mapping attribute slugs to their new values. + attributes: A list of Attribute objects associated with the current Entity. + + Returns: + A list of Value objects that can be bulk created. + """ + eav_values_to_create = [] + if not eav_values: + return eav_values_to_create + + ct = ContentType.objects.get_for_model(self.instance) + attribute_slugs = list(eav_values.keys()) + + for attr_slug in attribute_slugs: + entity_data = { + 'entity_ct': ct, + 'attribute': next( + ( + attribute + for attribute in attributes + if attribute.slug == attr_slug + ), + None, + ), + get_entity_pk_type(self): self.pk, + 'value': eav_values[attr_slug], + } + eav_values_to_create.append(Value(**entity_data)) + + return eav_values_to_create + class EAVModelMeta(ModelBase): def __new__(cls, name, bases, namespace, **kwds): From 6a80a3a22ca15b01677c91847c2ac106974bc6fc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:49:53 +0000 Subject: [PATCH 2/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- eav/models/entity.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eav/models/entity.py b/eav/models/entity.py index 357e8f3c..c658ff6f 100644 --- a/eav/models/entity.py +++ b/eav/models/entity.py @@ -233,8 +233,8 @@ def save_bulk( for attr_slug in attribute_slugs: entity_data = { - 'entity_ct': ct, - 'attribute': next( + "entity_ct": ct, + "attribute": next( ( attribute for attribute in attributes @@ -243,7 +243,7 @@ def save_bulk( None, ), get_entity_pk_type(self): self.pk, - 'value': eav_values[attr_slug], + "value": eav_values[attr_slug], } eav_values_to_create.append(Value(**entity_data)) From 2fddeab56f0247eb39257c1c3bf5a2c24a25f227 Mon Sep 17 00:00:00 2001 From: serbanPricop Date: Mon, 14 Oct 2024 18:13:33 +0300 Subject: [PATCH 3/5] feat(eav): add bulk save functionality to Entity model - Add `commit` parameter to `save` method - Implement `save_bulk` method for preparing bulk EAV Value objects - Modify `save` method to support bulk creation when `commit=False` - Update attribute value handling in `save` method --- eav/models/entity.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/eav/models/entity.py b/eav/models/entity.py index c658ff6f..ed1128f7 100644 --- a/eav/models/entity.py +++ b/eav/models/entity.py @@ -118,7 +118,9 @@ def save(self, commit=True): if commit: attribute.save_value(self.instance, attribute_value) values[attribute.slug] = attribute_value - self.save_bulk(values, attributes) + if not commit: + attributes_value = self.save_bulk(values, attributes) + Value.objects.bulk_create(attributes_value) def validate_attributes(self): """ @@ -233,8 +235,8 @@ def save_bulk( for attr_slug in attribute_slugs: entity_data = { - "entity_ct": ct, - "attribute": next( + 'entity_ct': ct, + 'attribute': next( ( attribute for attribute in attributes @@ -243,7 +245,7 @@ def save_bulk( None, ), get_entity_pk_type(self): self.pk, - "value": eav_values[attr_slug], + 'value': eav_values[attr_slug], } eav_values_to_create.append(Value(**entity_data)) From 29ceb874342bbc4b6195e587c090415ff08aee44 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:13:44 +0000 Subject: [PATCH 4/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- eav/models/entity.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/eav/models/entity.py b/eav/models/entity.py index ed1128f7..b941a789 100644 --- a/eav/models/entity.py +++ b/eav/models/entity.py @@ -235,8 +235,8 @@ def save_bulk( for attr_slug in attribute_slugs: entity_data = { - 'entity_ct': ct, - 'attribute': next( + "entity_ct": ct, + "attribute": next( ( attribute for attribute in attributes @@ -245,7 +245,7 @@ def save_bulk( None, ), get_entity_pk_type(self): self.pk, - 'value': eav_values[attr_slug], + "value": eav_values[attr_slug], } eav_values_to_create.append(Value(**entity_data)) From e3ae5b516d4fd817d022ffebed799d5c261e8a83 Mon Sep 17 00:00:00 2001 From: serbanPricop Date: Mon, 14 Oct 2024 23:30:19 +0300 Subject: [PATCH 5/5] style(entity): improve code style and consistency in Entity class - Change `save` method signature to use keyword-only argument --- eav/models/entity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eav/models/entity.py b/eav/models/entity.py index b941a789..f9d5ac12 100644 --- a/eav/models/entity.py +++ b/eav/models/entity.py @@ -99,7 +99,7 @@ def _getattr(self, attribute_slug): """ return self.__dict__[attribute_slug] - def save(self, commit=True): + def save(self, *, commit=True): """Saves all the EAV values that have been set on this entity.""" values = {} attributes = self.get_all_attributes()