Adds managment command to repair editions in bad state

This commit is contained in:
Mouse Reeve 2023-07-17 11:20:36 -07:00
parent fbb9d75cc8
commit eee4e30e25
3 changed files with 54 additions and 0 deletions

View file

@ -0,0 +1,21 @@
""" Repair editions with missing works """
from django.core.management.base import BaseCommand
from bookwyrm import models
class Commmand(BaseCommand):
"""command-line options"""
help = "Repairs an edition that is in a broken state"
# pylint: disable=unused-argument
def handle(self, *args, **options):
"""Find and repair broken editions"""
# Find broken editions
editions = models.Edition.objects.filter(parent_work__isnull=True)
self.stdout.write(f"Repairing {editions.count()} edition(s):")
# Do repair
for edition in editions:
edition.repair()
self.stdout.write(".", ending="")

View file

@ -126,6 +126,18 @@ class ActivitypubMixin:
# there OUGHT to be only one match
return match.first()
def get_dedpulication_field_json(self):
"""A json blob of deduplication fields (like remote_id, or ISBN)"""
data = {}
for field in self._meta.get_fields():
if (
not hasattr(field, "deduplication_field")
or not field.deduplication_field
):
continue
data[field.name] = getattr(self, field.name)
return data
def broadcast(self, activity, sender, software=None, queue=BROADCAST):
"""send out an activity"""
broadcast_task.apply_async(

View file

@ -2,6 +2,7 @@
from itertools import chain
import re
from django.apps import apps
from django.contrib.postgres.search import SearchVectorField
from django.contrib.postgres.indexes import GinIndex
from django.core.cache import cache
@ -380,6 +381,26 @@ class Edition(Book):
return super().save(*args, **kwargs)
def repair(self):
"""If an edition is in a bad state (missing a work), let's fix that"""
# made sure it actually NEEDS reapir
if self.parent_work:
return
# try to find a duplicate of this edition first
model = apps.get_model("bookwyrm.Edition", require_ready=True)
data = self.get_dedpulication_field_json()
existing_match = model.find_existing(data)
# assign this edition to the parent of the duplicate edition
new_work = existing_match.parent_work
# if not, create a new work for it
if not new_work:
new_work = models.Work.objects.create(title=self.title)
self.parent_work = new_work
self.save(update_fields=["parent_work"], broadcast=False)
@classmethod
def viewer_aware_objects(cls, viewer):
"""annotate a book query with metadata related to the user"""