Add command that merges tags
This commit is contained in:
1 file changed
+83
@@ -0,0 +1,83 @@
|
||||
from typing import Optional
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError, CommandParser
|
||||
from django.db import transaction
|
||||
|
||||
from sok.models import Publication, PublicationTag, Tag
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""
|
||||
Merges `rhs` into `lhs`.
|
||||
"""
|
||||
|
||||
def echo(self, msg: str):
|
||||
self.stdout.write(msg)
|
||||
|
||||
def success(self, msg: str):
|
||||
self.echo(self.style.SUCCESS(msg))
|
||||
|
||||
def get_tag(self, value: str) -> Tag:
|
||||
try:
|
||||
pk = int(value)
|
||||
return Tag.objects.get(pk=pk)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
return Tag.objects.get(name=value)
|
||||
except Tag.DoesNotExist:
|
||||
pass
|
||||
|
||||
return Tag.objects.get(name__icontains=value)
|
||||
|
||||
def get_rel(self, publication: Publication, tag: Tag) -> Optional[PublicationTag]:
|
||||
try:
|
||||
return PublicationTag.objects.get(publication=publication, tag=tag)
|
||||
except PublicationTag.DoesNotExist:
|
||||
return None
|
||||
|
||||
@transaction.atomic
|
||||
def merge(self, lhs: Tag, rhs: Tag, publication: Publication):
|
||||
assert lhs.pk != rhs.pk
|
||||
|
||||
rhs_rel = PublicationTag.objects.get(publication=publication, tag=rhs)
|
||||
lhs_rel, created = PublicationTag.objects.get_or_create(
|
||||
publication=publication,
|
||||
tag=lhs,
|
||||
)
|
||||
|
||||
changed = False
|
||||
if lhs_cmt := lhs_rel.comment:
|
||||
if rhs_cmt := rhs_rel.comment:
|
||||
if lhs_cmt != rhs_cmt:
|
||||
lhs_rel.cmt = f"{lhs_cmt}; {rhs_cmt}"
|
||||
changed = True
|
||||
else:
|
||||
lhs_rel.comment = rhs_rel.comment
|
||||
changed = True
|
||||
|
||||
rhs.publications.remove(publication)
|
||||
|
||||
if changed:
|
||||
lhs_rel.full_clean()
|
||||
lhs_rel.save()
|
||||
self.success(f"{lhs} <- {rhs} [{publication.cite_key}]: {lhs_rel.comment}")
|
||||
else:
|
||||
self.success(f"{lhs} <- {rhs} [{publication.cite_key}]")
|
||||
|
||||
# BaseCommand
|
||||
|
||||
def add_arguments(self, parser: CommandParser):
|
||||
parser.add_argument('lhs')
|
||||
parser.add_argument('rhs')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
lhs = self.get_tag(options['lhs'])
|
||||
rhs = self.get_tag(options['rhs'])
|
||||
|
||||
if lhs == rhs:
|
||||
raise CommandError(f"Cannot merge tag with itself: {lhs}")
|
||||
|
||||
for publication in rhs.publications.all():
|
||||
self.merge(lhs, rhs, publication)
|
||||
Reference in new issue
Block a user