def add_bulk_activity(
instances: Iterable[ActivityMixin],
user: User,
verb: str,
using: str | None = None
) -> list[Activity]:
bounded_instances = list(itertools.islice(iter(instances), BULK_ACTIVITY_COUNT_MAX + 1))
if len(bounded_instances) > BULK_ACTIVITY_COUNT_MAX:
log.warning(
'add_bulk_activity truncated "%s" activity records to the %d row cap; '
'the audit trail for this operation is incomplete.',
verb,
BULK_ACTIVITY_COUNT_MAX,
)
bounded_instances = bounded_instances[:BULK_ACTIVITY_COUNT_MAX]
instance_list = [
instance
for instance in bounded_instances
if instance.pk is not None
]
skipped_count = len(bounded_instances) - len(instance_list)
if skipped_count > 0:
log.warning(
'add_bulk_activity skipped %d "%s" activity records for instances without '
'primary keys (unsaved objects, bulk_create with ignore_conflicts, or a '
'database backend that cannot return inserted rows).',
skipped_count,
verb,
)
if not instance_list:
return []
content_type = ContentType.objects.get_for_model(instance_list[0])
activities = [
Activity(
content_type=content_type,
object_id=instance.pk,
user=user,
verb=verb,
information=build_activity_information(instance, user, verb)
)
for instance in instance_list
]
return _activity_manager(using).bulk_create(activities)