Skip to content

Commit

Permalink
Make it easier to change the identifiers mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
viggo-devries committed Dec 15, 2023
1 parent 7696489 commit 12648fe
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 33 deletions.
6 changes: 4 additions & 2 deletions oscar_odin/mappings/catalogue.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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.
Expand All @@ -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 = {}

Expand Down
16 changes: 16 additions & 0 deletions oscar_odin/mappings/constants.py
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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",),
}
40 changes: 10 additions & 30 deletions oscar_odin/mappings/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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)
Expand All @@ -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):
Expand All @@ -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 [
Expand All @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion oscar_odin/mappings/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 12648fe

Please sign in to comment.