|
8 | 8 | from oscar.core.loading import get_model |
9 | 9 | from oscar.apps.catalogue.product_attributes import QuerysetCache |
10 | 10 |
|
11 | | -from ..utils import ErrorLog, in_bulk |
| 11 | +from ..utils import ErrorLog, in_bulk, chunked |
12 | 12 | from ..exceptions import OscarOdinException |
13 | 13 | from .constants import MODEL_IDENTIFIERS_MAPPING |
14 | 14 |
|
@@ -315,20 +315,37 @@ def bulk_update_or_create_one_to_many(self): |
315 | 315 | )[0] |
316 | 316 | fields = self.get_fields_to_update(relation.related_model) |
317 | 317 | if fields is not None: |
318 | | - conditions = Q() |
319 | 318 | identifiers = self.identifier_mapping[relation.related_model] |
320 | | - for key in set(keys): |
321 | | - if isinstance(key, (list, tuple)): |
322 | | - conditions |= Q(**dict(list(zip(identifiers, key)))) |
323 | | - else: |
324 | | - conditions |= Q(**{f"{identifiers[0]}": key}) |
325 | 319 | field_name = f"{relation.remote_field.name}__{instance_identifier}" |
| 320 | + |
| 321 | + ids_to_keep = set() |
| 322 | + unique_keys = list(set(keys)) |
| 323 | + |
| 324 | + for key_chunk in chunked(unique_keys): |
| 325 | + conditions = Q() |
| 326 | + |
| 327 | + for key in key_chunk: |
| 328 | + if isinstance(key, (list, tuple)): |
| 329 | + conditions |= Q(**dict(list(zip(identifiers, key)))) |
| 330 | + else: |
| 331 | + conditions |= Q(**{f"{identifiers[0]}": key}) |
| 332 | + |
| 333 | + chunk_ids = ( |
| 334 | + relation.related_model.objects.filter( |
| 335 | + **{f"{field_name}__in": self.instance_keys} |
| 336 | + ) |
| 337 | + .filter(conditions) |
| 338 | + .values_list("id", flat=True) |
| 339 | + ) |
| 340 | + |
| 341 | + ids_to_keep.update(chunk_ids) |
| 342 | + |
326 | 343 | # Delete all related one_to_many instances where product is in the |
327 | 344 | # given list of resources and excluding any instances present in |
328 | 345 | # those resources |
329 | 346 | relation.related_model.objects.filter( |
330 | 347 | **{f"{field_name}__in": self.instance_keys} |
331 | | - ).exclude(conditions).delete() |
| 348 | + ).exclude(id__in=ids_to_keep).delete() |
332 | 349 |
|
333 | 350 | def bulk_update_or_create_many_to_many(self): |
334 | 351 | m2m_to_create, m2m_to_update, _ = self.get_all_m2m_relations |
|
0 commit comments