mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2026-01-03 01:15:57 +10:00
Use bulk operations for add/remove tags actions
- add_tags: Uses SnapshotTag.objects.bulk_create() with ignore_conflicts Instead of N calls to obj.tags.add(), now makes 1 query per tag - remove_tags: Uses single SnapshotTag.objects.filter().delete() Instead of N calls to obj.tags.remove(), now makes 1 query total Works correctly with "select all across pages" via queryset.values_list()
This commit is contained in:
@@ -498,6 +498,8 @@ class SnapshotAdmin(SearchResultsAdminMixin, ConfigEditorMixin, BaseModelAdmin):
|
||||
description="+"
|
||||
)
|
||||
def add_tags(self, request, queryset):
|
||||
from archivebox.core.models import SnapshotTag
|
||||
|
||||
# Get tags from the form - now comma-separated string
|
||||
tags_str = request.POST.get('tags', '')
|
||||
if not tags_str:
|
||||
@@ -515,12 +517,22 @@ class SnapshotAdmin(SearchResultsAdminMixin, ConfigEditorMixin, BaseModelAdmin):
|
||||
tag = Tag.objects.filter(name__iexact=name).first() or tag
|
||||
tags.append(tag)
|
||||
|
||||
print('[+] Adding tags', [t.name for t in tags], 'to Snapshots', queryset)
|
||||
for obj in queryset:
|
||||
obj.tags.add(*tags)
|
||||
# Get snapshot IDs efficiently (works with select_across for all pages)
|
||||
snapshot_ids = list(queryset.values_list('id', flat=True))
|
||||
num_snapshots = len(snapshot_ids)
|
||||
|
||||
print('[+] Adding tags', [t.name for t in tags], 'to', num_snapshots, 'Snapshots')
|
||||
|
||||
# Bulk create M2M relationships (1 query per tag, not per snapshot)
|
||||
for tag in tags:
|
||||
SnapshotTag.objects.bulk_create(
|
||||
[SnapshotTag(snapshot_id=sid, tag=tag) for sid in snapshot_ids],
|
||||
ignore_conflicts=True # Skip if relationship already exists
|
||||
)
|
||||
|
||||
messages.success(
|
||||
request,
|
||||
f"Added {len(tags)} tag(s) to {queryset.count()} Snapshot(s).",
|
||||
f"Added {len(tags)} tag(s) to {num_snapshots} Snapshot(s).",
|
||||
)
|
||||
|
||||
|
||||
@@ -528,6 +540,8 @@ class SnapshotAdmin(SearchResultsAdminMixin, ConfigEditorMixin, BaseModelAdmin):
|
||||
description="–"
|
||||
)
|
||||
def remove_tags(self, request, queryset):
|
||||
from archivebox.core.models import SnapshotTag
|
||||
|
||||
# Get tags from the form - now comma-separated string
|
||||
tags_str = request.POST.get('tags', '')
|
||||
if not tags_str:
|
||||
@@ -542,10 +556,24 @@ class SnapshotAdmin(SearchResultsAdminMixin, ConfigEditorMixin, BaseModelAdmin):
|
||||
if tag:
|
||||
tags.append(tag)
|
||||
|
||||
print('[-] Removing tags', [t.name for t in tags], 'from Snapshots', queryset)
|
||||
for obj in queryset:
|
||||
obj.tags.remove(*tags)
|
||||
if not tags:
|
||||
messages.warning(request, "No matching tags found.")
|
||||
return
|
||||
|
||||
# Get snapshot IDs efficiently (works with select_across for all pages)
|
||||
snapshot_ids = list(queryset.values_list('id', flat=True))
|
||||
num_snapshots = len(snapshot_ids)
|
||||
tag_ids = [t.pk for t in tags]
|
||||
|
||||
print('[-] Removing tags', [t.name for t in tags], 'from', num_snapshots, 'Snapshots')
|
||||
|
||||
# Bulk delete M2M relationships (1 query total, not per snapshot)
|
||||
deleted_count, _ = SnapshotTag.objects.filter(
|
||||
snapshot_id__in=snapshot_ids,
|
||||
tag_id__in=tag_ids
|
||||
).delete()
|
||||
|
||||
messages.success(
|
||||
request,
|
||||
f"Removed {len(tags)} tag(s) from {queryset.count()} Snapshot(s).",
|
||||
f"Removed {len(tags)} tag(s) from {num_snapshots} Snapshot(s) ({deleted_count} associations deleted).",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user