Skip to content

Commit 2131d0e

Browse files
joeyjurjensJoey Jurjens
andauthored
Collect excluded ids in chunks because sometimes it would raise an 'Expression tree is too large' error. (#75)
Co-authored-by: Joey Jurjens <[email protected]>
1 parent 428b655 commit 2131d0e

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

oscar_odin/mappings/context.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from oscar.core.loading import get_model
99
from oscar.apps.catalogue.product_attributes import QuerysetCache
1010

11-
from ..utils import ErrorLog, in_bulk
11+
from ..utils import ErrorLog, in_bulk, chunked
1212
from ..exceptions import OscarOdinException
1313
from .constants import MODEL_IDENTIFIERS_MAPPING
1414

@@ -315,20 +315,37 @@ def bulk_update_or_create_one_to_many(self):
315315
)[0]
316316
fields = self.get_fields_to_update(relation.related_model)
317317
if fields is not None:
318-
conditions = Q()
319318
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})
325319
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+
326343
# Delete all related one_to_many instances where product is in the
327344
# given list of resources and excluding any instances present in
328345
# those resources
329346
relation.related_model.objects.filter(
330347
**{f"{field_name}__in": self.instance_keys}
331-
).exclude(conditions).delete()
348+
).exclude(id__in=ids_to_keep).delete()
332349

333350
def bulk_update_or_create_many_to_many(self):
334351
m2m_to_create, m2m_to_update, _ = self.get_all_m2m_relations

0 commit comments

Comments
 (0)