def apply(
self,
model: type[SyncableMixin],
pending: dict[str, dict[str, list[Any]]],
) -> UpsertResult:
result = UpsertResult()
if not pending:
return result
identity_lookup = {f'{self._identity_field}__in': list(pending.keys())}
instances_by_key = {
str(getattr(instance, self._identity_field)): instance
for instance in model.objects.filter(**identity_lookup)
}
with sync_bypass():
for key in sorted(pending.keys()):
many_to_many_data = pending[key]
instance = instances_by_key.get(key)
if instance is None:
logger.warning(
'Skipping M2M relations for %s key=%s: '
'instance not found after upsert',
model._meta.label,
key,
)
result.skipped.add(key)
continue
for field_name, values in sorted(many_to_many_data.items()):
try:
getattr(instance, field_name).set(values)
except IntegrityError as exception:
logger.exception(
'M2M set failed for %s:%s field=%s values=%s',
model._meta.label,
key,
field_name,
values,
)
result.errors.append(Error(
key=key,
message=(
f'M2M set failed for '
f'{model._meta.label}:{key} '
f'field={field_name}: {exception}'
),
exception=exception,
))
return result