Skip to content

Commit

Permalink
Use updates to the mapper to provide a cleaner interface for the orde…
Browse files Browse the repository at this point in the history
…ring of save operations.
  • Loading branch information
timsavage committed Nov 23, 2023
1 parent 78ff4b0 commit 3f9f974
Showing 1 changed file with 26 additions and 7 deletions.
33 changes: 26 additions & 7 deletions oscar_odin/mappings/catalogue.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""Mappings between odin and django-oscar models."""
from decimal import Decimal
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union, NamedTuple

import odin
from django.contrib.auth.models import AbstractUser
from django.db import transaction
from django.db.models import QuerySet
from django.db.models import QuerySet, Model, ManyToManyField, ForeignKey
from django.db.models.fields.files import ImageFieldFile
from django.http import HttpRequest
from oscar.apps.partner.strategy import Default as DefaultStrategy
Expand Down Expand Up @@ -321,15 +321,34 @@ def product_queryset_to_resources(
)


ForeignRelationResult = Tuple[Model, ManyToManyField, Any]


class RelatedModels(NamedTuple):
@classmethod
def from_context(cls, context: dict):
return cls(
context["one_to_many_items"],
context["many_to_one_items"],
context["many_to_many_items"],
context["foreign_key_items"],
)

one_to_many_items: ForeignRelationResult
many_to_one_items: ForeignRelationResult
many_to_many_items: ForeignRelationResult
foreign_key_items: Tuple[Model, ForeignKey, Any]


def product_to_model(
product: resources.catalogue.Product,
) -> ProductModel:
) -> Tuple[ProductModel, RelatedModels]:
"""Map a product resource to a model."""
context = {"original_object": product}

obj = ProductToModel.apply(product, context=context)

return obj, context
return (obj, RelatedModels.from_context(context))


def product_to_db(
Expand All @@ -340,10 +359,10 @@ def product_to_db(
The method will handle the nested database saves required to store the entire resource
within a single transaction.
"""
obj, context = product_to_model(product)
obj, related_models = product_to_model(product)

with transaction.atomic():
for fk_name, fk_attname, fk_instance in context.get("foreign_key_items", []):
for parent, field, fk_instance in related_models.foreign_key_items:
fk_instance.save()
setattr(obj, fk_name, fk_instance.pk)

Expand Down

0 comments on commit 3f9f974

Please sign in to comment.