Skip to content

Commit

Permalink
Merge pull request #48 from django-oscar/resources-to-db
Browse files Browse the repository at this point in the history
[FEAT] Import resources to database
  • Loading branch information
specialunderwear authored Nov 1, 2024
2 parents 3dafbd5 + cf8d958 commit fe7dc0c
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
10 changes: 4 additions & 6 deletions oscar_odin/mappings/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ def bulk_update_or_create_instances(self, instances):
self.Model.objects.bulk_update(validated_instances_to_update, fields=fields)

def bulk_update_or_create_one_to_many(self):
for relation, product, instances in self.get_all_o2m_instances:
for relation, parent, instances in self.get_all_o2m_instances:
for instance in instances:
setattr(instance, relation.field.name, product)
setattr(instance, relation.field.name, parent)

instances_to_create, instances_to_update, identities = self.get_o2m_relations

Expand Down Expand Up @@ -315,14 +315,12 @@ def bulk_update_or_create_one_to_many(self):
if fields is not None:
conditions = Q()
identifiers = self.identifier_mapping[relation.related_model]
for key in keys:
for key in set(keys):
if isinstance(key, (list, tuple)):
conditions |= Q(**dict(list(zip(identifiers, key))))
else:
conditions |= Q(**{f"{identifiers[0]}": key})
field_name = relation.remote_field.attname.replace(
"_", "__"
).replace("id", instance_identifier)
field_name = f"{relation.remote_field.name}__{instance_identifier}"
# Delete all related one_to_many instances where product is in the
# given list of resources and excluding any instances present in
# those resources
Expand Down
44 changes: 44 additions & 0 deletions oscar_odin/mappings/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from oscar_odin.mappings.context import ModelMapperContext
from oscar_odin.utils import validate_resources


def resources_to_db(
resources,
fields_to_update,
identifier_mapping,
model_mapper,
delete_related=False,
clean_instances=True,
skip_invalid_resources=False,
error_identifiers=None,
):
"""Map mulitple resources to a model and store them in the database.
The method will first bulk update or create the foreign keys
After that all the resources will be bulk saved.
At last all related models can will be saved and set on the record.
"""
error_identifiers = error_identifiers or identifier_mapping.get(model_mapper.to_obj)
valid_resources, resource_errors = validate_resources(resources, error_identifiers)
if not skip_invalid_resources and resource_errors:
return [], resource_errors

context = ModelMapperContext(
model_mapper.to_obj,
delete_related=delete_related,
error_identifiers=error_identifiers,
)
result = model_mapper.apply(valid_resources, context=context)

try:
instances = list(result)
except TypeError: # it is not a list
instances = [result]

saved_resources, errors = context.bulk_save(
instances,
fields_to_update,
identifier_mapping,
clean_instances,
)
return saved_resources, resource_errors + errors

0 comments on commit fe7dc0c

Please sign in to comment.