From 12648fe9f8239ddb1d014f7309734bd5c6f10662 Mon Sep 17 00:00:00 2001 From: Viggo de Vries Date: Fri, 15 Dec 2023 11:28:05 +0100 Subject: [PATCH] Make it easier to change the identifiers mapping --- oscar_odin/mappings/catalogue.py | 6 +++-- oscar_odin/mappings/constants.py | 16 +++++++++++++ oscar_odin/mappings/context.py | 40 ++++++++------------------------ oscar_odin/mappings/utils.py | 2 +- 4 files changed, 31 insertions(+), 33 deletions(-) diff --git a/oscar_odin/mappings/catalogue.py b/oscar_odin/mappings/catalogue.py index 6ffa58b..b8f6366 100644 --- a/oscar_odin/mappings/catalogue.py +++ b/oscar_odin/mappings/catalogue.py @@ -26,7 +26,7 @@ save_foreign_keys, ) from .context import ModelMapperContext -from .constants import ALL_CATALOGUE_FIELDS +from .constants import ALL_CATALOGUE_FIELDS, MODEL_IDENTIFIERS_MAPPING __all__ = ( "ProductImageToResource", @@ -393,6 +393,7 @@ def products_to_db( products: List[resources.catalogue.Product], rollback=True, fields_to_update=ALL_CATALOGUE_FIELDS, + identifier_mapping=MODEL_IDENTIFIERS_MAPPING, ) -> Tuple[List[ProductModel], Dict]: """Map mulitple products to a model and store them in the database. @@ -401,7 +402,8 @@ def products_to_db( At last all related models like images, stockrecords, and related_products can will be saved and set on the product. """ instances, context = products_to_model(products) - context.add_fields_to_update(fields_to_update) + context.fields_to_update = fields_to_update + context.identifier_mapping = identifier_mapping errors = {} diff --git a/oscar_odin/mappings/constants.py b/oscar_odin/mappings/constants.py index f207bf9..b6fa471 100644 --- a/oscar_odin/mappings/constants.py +++ b/oscar_odin/mappings/constants.py @@ -1,3 +1,11 @@ +from oscar.core.loading import get_model + +Product = get_model("catalogue", "Product") +Category = get_model("catalogue", "Category") +StockRecord = get_model("partner", "StockRecord") +ProductClass = get_model("catalogue", "ProductClass") +ProductImage = get_model("catalogue", "ProductImage") + PRODUCT_STRUCTURE = "Product.structure" PRODUCT_IS_PUBLIC = "Product.is_public" PRODUCT_UPC = "Product.upc" @@ -76,3 +84,11 @@ ALL_CATALOGUE_FIELDS = ( ALL_PRODUCT_FIELDS + ALL_PRODUCTIMAGE_FIELDS + ALL_STOCKRECORD_FIELDS ) + +MODEL_IDENTIFIERS_MAPPING = { + Category: ("code",), + Product: ("upc",), + StockRecord: ("product_id",), + ProductClass: ("slug",), + ProductImage: ("code",), +} diff --git a/oscar_odin/mappings/context.py b/oscar_odin/mappings/context.py index ae564aa..4138d1e 100644 --- a/oscar_odin/mappings/context.py +++ b/oscar_odin/mappings/context.py @@ -14,33 +14,11 @@ ProductImage = get_model("catalogue", "ProductImage") -MODEL_IDENTIFIERS_MAPPING = { - Category: ("code",), - Product: ("upc",), - StockRecord: ("product_id",), - ProductClass: ("slug",), - ProductImage: ("code",), -} - - -def get_unique_id_list(Model, instances): - unique_id_list = [] - identifiers = MODEL_IDENTIFIERS_MAPPING.get(Model, {}) - - if identifiers: - for instance in instances: - unique_id_list.append( - [getattr(instance, identifier) for identifier in identifiers] - ) - - return unique_id_list, identifiers - - -def get_instances_to_create_or_update(Model, instances): +def get_instances_to_create_or_update(Model, instances, identifier_mapping): instances_to_create = [] instances_to_update = [] - unique_id_list, identifiers = get_unique_id_list(Model, instances) + identifiers = identifier_mapping.get(Model, {}) if identifiers: id_mapping = in_bulk( @@ -72,8 +50,8 @@ class ModelMapperContext(dict): many_to_many_items = None many_to_one_items = None one_to_many_items = None - source_fields = None attribute_data = None + identifier_mapping = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -82,6 +60,7 @@ def __init__(self, *args, **kwargs): self.many_to_one_items = defaultdict(list) self.one_to_many_items = defaultdict(list) self.fields_to_update = defaultdict(list) + self.identifier_mapping = defaultdict(tuple) self.attribute_data = [] def __bool__(self): @@ -103,9 +82,6 @@ def add_instance_to_fk_items(self, field, instance): if not instance.pk: self.foreign_key_items[field] += [instance] - def add_fields_to_update(self, fields_to_update): - self.fields_to_update = fields_to_update - def get_fields_to_update(self, Model): modelname = "%s." % Model.__name__ return [ @@ -127,7 +103,9 @@ def get_create_and_update_relations(self, related_instance_items): ( instances_to_create, instances_to_update, - ) = get_instances_to_create_or_update(relation.related_model, all_instances) + ) = get_instances_to_create_or_update( + relation.related_model, all_instances, self.identifier_mapping + ) to_create[relation].extend(instances_to_create) to_update[relation].extend(instances_to_update) @@ -152,7 +130,9 @@ def get_fk_relations(self): ( instances_to_create, instances_to_update, - ) = get_instances_to_create_or_update(relation.related_model, instances) + ) = get_instances_to_create_or_update( + relation.related_model, instances, self.identifier_mapping + ) to_create[relation].extend(instances_to_create) to_update[relation].extend(instances_to_update) diff --git a/oscar_odin/mappings/utils.py b/oscar_odin/mappings/utils.py index 786f220..7c484e0 100644 --- a/oscar_odin/mappings/utils.py +++ b/oscar_odin/mappings/utils.py @@ -37,7 +37,7 @@ def save_foreign_keys(context, errors): def save_products(instances, context, errors): instances_to_create, instances_to_update = get_instances_to_create_or_update( - Product, instances + Product, instances, context.identifier_mapping ) validated_create_instances, errors = validate_instances(instances_to_create, errors)