Runs black
This commit is contained in:
@ -1,26 +1,20 @@
|
||||
''' PROCEED WITH CAUTION: uses deduplication fields to permanently
|
||||
merge book data objects '''
|
||||
""" PROCEED WITH CAUTION: uses deduplication fields to permanently
|
||||
merge book data objects """
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count
|
||||
from bookwyrm import models
|
||||
|
||||
|
||||
def update_related(canonical, obj):
|
||||
''' update all the models with fk to the object being removed '''
|
||||
""" update all the models with fk to the object being removed """
|
||||
# move related models to canonical
|
||||
related_models = [
|
||||
(r.remote_field.name, r.related_model) for r in \
|
||||
canonical._meta.related_objects]
|
||||
(r.remote_field.name, r.related_model) for r in canonical._meta.related_objects
|
||||
]
|
||||
for (related_field, related_model) in related_models:
|
||||
related_objs = related_model.objects.filter(
|
||||
**{related_field: obj})
|
||||
related_objs = related_model.objects.filter(**{related_field: obj})
|
||||
for related_obj in related_objs:
|
||||
print(
|
||||
'replacing in',
|
||||
related_model.__name__,
|
||||
related_field,
|
||||
related_obj.id
|
||||
)
|
||||
print("replacing in", related_model.__name__, related_field, related_obj.id)
|
||||
try:
|
||||
setattr(related_obj, related_field, canonical)
|
||||
related_obj.save()
|
||||
@ -30,40 +24,41 @@ def update_related(canonical, obj):
|
||||
|
||||
|
||||
def copy_data(canonical, obj):
|
||||
''' try to get the most data possible '''
|
||||
""" try to get the most data possible """
|
||||
for data_field in obj._meta.get_fields():
|
||||
if not hasattr(data_field, 'activitypub_field'):
|
||||
if not hasattr(data_field, "activitypub_field"):
|
||||
continue
|
||||
data_value = getattr(obj, data_field.name)
|
||||
if not data_value:
|
||||
continue
|
||||
if not getattr(canonical, data_field.name):
|
||||
print('setting data field', data_field.name, data_value)
|
||||
print("setting data field", data_field.name, data_value)
|
||||
setattr(canonical, data_field.name, data_value)
|
||||
canonical.save()
|
||||
|
||||
|
||||
def dedupe_model(model):
|
||||
''' combine duplicate editions and update related models '''
|
||||
""" combine duplicate editions and update related models """
|
||||
fields = model._meta.get_fields()
|
||||
dedupe_fields = [f for f in fields if \
|
||||
hasattr(f, 'deduplication_field') and f.deduplication_field]
|
||||
dedupe_fields = [
|
||||
f for f in fields if hasattr(f, "deduplication_field") and f.deduplication_field
|
||||
]
|
||||
for field in dedupe_fields:
|
||||
dupes = model.objects.values(field.name).annotate(
|
||||
Count(field.name)
|
||||
).filter(**{'%s__count__gt' % field.name: 1})
|
||||
dupes = (
|
||||
model.objects.values(field.name)
|
||||
.annotate(Count(field.name))
|
||||
.filter(**{"%s__count__gt" % field.name: 1})
|
||||
)
|
||||
|
||||
for dupe in dupes:
|
||||
value = dupe[field.name]
|
||||
if not value or value == '':
|
||||
if not value or value == "":
|
||||
continue
|
||||
print('----------')
|
||||
print("----------")
|
||||
print(dupe)
|
||||
objs = model.objects.filter(
|
||||
**{field.name: value}
|
||||
).order_by('id')
|
||||
objs = model.objects.filter(**{field.name: value}).order_by("id")
|
||||
canonical = objs.first()
|
||||
print('keeping', canonical.remote_id)
|
||||
print("keeping", canonical.remote_id)
|
||||
for obj in objs[1:]:
|
||||
print(obj.remote_id)
|
||||
copy_data(canonical, obj)
|
||||
@ -73,11 +68,12 @@ def dedupe_model(model):
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
''' dedplucate allllll the book data models '''
|
||||
help = 'merges duplicate book data'
|
||||
""" dedplucate allllll the book data models """
|
||||
|
||||
help = "merges duplicate book data"
|
||||
# pylint: disable=no-self-use,unused-argument
|
||||
def handle(self, *args, **options):
|
||||
''' run deudplications '''
|
||||
""" run deudplications """
|
||||
dedupe_model(models.Edition)
|
||||
dedupe_model(models.Work)
|
||||
dedupe_model(models.Author)
|
||||
|
@ -5,51 +5,63 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from bookwyrm.models import Connector, SiteSettings, User
|
||||
from bookwyrm.settings import DOMAIN
|
||||
|
||||
|
||||
def init_groups():
|
||||
groups = ['admin', 'moderator', 'editor']
|
||||
groups = ["admin", "moderator", "editor"]
|
||||
for group in groups:
|
||||
Group.objects.create(name=group)
|
||||
|
||||
|
||||
def init_permissions():
|
||||
permissions = [{
|
||||
'codename': 'edit_instance_settings',
|
||||
'name': 'change the instance info',
|
||||
'groups': ['admin',]
|
||||
}, {
|
||||
'codename': 'set_user_group',
|
||||
'name': 'change what group a user is in',
|
||||
'groups': ['admin', 'moderator']
|
||||
}, {
|
||||
'codename': 'control_federation',
|
||||
'name': 'control who to federate with',
|
||||
'groups': ['admin', 'moderator']
|
||||
}, {
|
||||
'codename': 'create_invites',
|
||||
'name': 'issue invitations to join',
|
||||
'groups': ['admin', 'moderator']
|
||||
}, {
|
||||
'codename': 'moderate_user',
|
||||
'name': 'deactivate or silence a user',
|
||||
'groups': ['admin', 'moderator']
|
||||
}, {
|
||||
'codename': 'moderate_post',
|
||||
'name': 'delete other users\' posts',
|
||||
'groups': ['admin', 'moderator']
|
||||
}, {
|
||||
'codename': 'edit_book',
|
||||
'name': 'edit book info',
|
||||
'groups': ['admin', 'moderator', 'editor']
|
||||
}]
|
||||
permissions = [
|
||||
{
|
||||
"codename": "edit_instance_settings",
|
||||
"name": "change the instance info",
|
||||
"groups": [
|
||||
"admin",
|
||||
],
|
||||
},
|
||||
{
|
||||
"codename": "set_user_group",
|
||||
"name": "change what group a user is in",
|
||||
"groups": ["admin", "moderator"],
|
||||
},
|
||||
{
|
||||
"codename": "control_federation",
|
||||
"name": "control who to federate with",
|
||||
"groups": ["admin", "moderator"],
|
||||
},
|
||||
{
|
||||
"codename": "create_invites",
|
||||
"name": "issue invitations to join",
|
||||
"groups": ["admin", "moderator"],
|
||||
},
|
||||
{
|
||||
"codename": "moderate_user",
|
||||
"name": "deactivate or silence a user",
|
||||
"groups": ["admin", "moderator"],
|
||||
},
|
||||
{
|
||||
"codename": "moderate_post",
|
||||
"name": "delete other users' posts",
|
||||
"groups": ["admin", "moderator"],
|
||||
},
|
||||
{
|
||||
"codename": "edit_book",
|
||||
"name": "edit book info",
|
||||
"groups": ["admin", "moderator", "editor"],
|
||||
},
|
||||
]
|
||||
|
||||
content_type = ContentType.objects.get_for_model(User)
|
||||
for permission in permissions:
|
||||
permission_obj = Permission.objects.create(
|
||||
codename=permission['codename'],
|
||||
name=permission['name'],
|
||||
codename=permission["codename"],
|
||||
name=permission["name"],
|
||||
content_type=content_type,
|
||||
)
|
||||
# add the permission to the appropriate groups
|
||||
for group_name in permission['groups']:
|
||||
for group_name in permission["groups"]:
|
||||
Group.objects.get(name=group_name).permissions.add(permission_obj)
|
||||
|
||||
# while the groups and permissions shouldn't be changed because the code
|
||||
@ -59,46 +71,48 @@ def init_permissions():
|
||||
def init_connectors():
|
||||
Connector.objects.create(
|
||||
identifier=DOMAIN,
|
||||
name='Local',
|
||||
name="Local",
|
||||
local=True,
|
||||
connector_file='self_connector',
|
||||
base_url='https://%s' % DOMAIN,
|
||||
books_url='https://%s/book' % DOMAIN,
|
||||
covers_url='https://%s/images/covers' % DOMAIN,
|
||||
search_url='https://%s/search?q=' % DOMAIN,
|
||||
isbn_search_url='https://%s/isbn/' % DOMAIN,
|
||||
connector_file="self_connector",
|
||||
base_url="https://%s" % DOMAIN,
|
||||
books_url="https://%s/book" % DOMAIN,
|
||||
covers_url="https://%s/images/covers" % DOMAIN,
|
||||
search_url="https://%s/search?q=" % DOMAIN,
|
||||
isbn_search_url="https://%s/isbn/" % DOMAIN,
|
||||
priority=1,
|
||||
)
|
||||
|
||||
Connector.objects.create(
|
||||
identifier='bookwyrm.social',
|
||||
name='BookWyrm dot Social',
|
||||
connector_file='bookwyrm_connector',
|
||||
base_url='https://bookwyrm.social',
|
||||
books_url='https://bookwyrm.social/book',
|
||||
covers_url='https://bookwyrm.social/images/covers',
|
||||
search_url='https://bookwyrm.social/search?q=',
|
||||
isbn_search_url='https://bookwyrm.social/isbn/',
|
||||
identifier="bookwyrm.social",
|
||||
name="BookWyrm dot Social",
|
||||
connector_file="bookwyrm_connector",
|
||||
base_url="https://bookwyrm.social",
|
||||
books_url="https://bookwyrm.social/book",
|
||||
covers_url="https://bookwyrm.social/images/covers",
|
||||
search_url="https://bookwyrm.social/search?q=",
|
||||
isbn_search_url="https://bookwyrm.social/isbn/",
|
||||
priority=2,
|
||||
)
|
||||
|
||||
Connector.objects.create(
|
||||
identifier='openlibrary.org',
|
||||
name='OpenLibrary',
|
||||
connector_file='openlibrary',
|
||||
base_url='https://openlibrary.org',
|
||||
books_url='https://openlibrary.org',
|
||||
covers_url='https://covers.openlibrary.org',
|
||||
search_url='https://openlibrary.org/search?q=',
|
||||
isbn_search_url='https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:',
|
||||
identifier="openlibrary.org",
|
||||
name="OpenLibrary",
|
||||
connector_file="openlibrary",
|
||||
base_url="https://openlibrary.org",
|
||||
books_url="https://openlibrary.org",
|
||||
covers_url="https://covers.openlibrary.org",
|
||||
search_url="https://openlibrary.org/search?q=",
|
||||
isbn_search_url="https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:",
|
||||
priority=3,
|
||||
)
|
||||
|
||||
|
||||
def init_settings():
|
||||
SiteSettings.objects.create()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Initializes the database with starter data'
|
||||
help = "Initializes the database with starter data"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
init_groups()
|
||||
|
@ -1,34 +1,42 @@
|
||||
''' PROCEED WITH CAUTION: this permanently deletes book data '''
|
||||
""" PROCEED WITH CAUTION: this permanently deletes book data """
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count, Q
|
||||
from bookwyrm import models
|
||||
|
||||
|
||||
def remove_editions():
|
||||
''' combine duplicate editions and update related models '''
|
||||
""" combine duplicate editions and update related models """
|
||||
# not in use
|
||||
filters = {'%s__isnull' % r.name: True \
|
||||
for r in models.Edition._meta.related_objects}
|
||||
filters = {
|
||||
"%s__isnull" % r.name: True for r in models.Edition._meta.related_objects
|
||||
}
|
||||
# no cover, no identifying fields
|
||||
filters['cover'] = ''
|
||||
null_fields = {'%s__isnull' % f: True for f in \
|
||||
['isbn_10', 'isbn_13', 'oclc_number']}
|
||||
filters["cover"] = ""
|
||||
null_fields = {
|
||||
"%s__isnull" % f: True for f in ["isbn_10", "isbn_13", "oclc_number"]
|
||||
}
|
||||
|
||||
editions = models.Edition.objects.filter(
|
||||
Q(languages=[]) | Q(languages__contains=['English']),
|
||||
**filters, **null_fields
|
||||
).annotate(Count('parent_work__editions')).filter(
|
||||
# mustn't be the only edition for the work
|
||||
parent_work__editions__count__gt=1
|
||||
editions = (
|
||||
models.Edition.objects.filter(
|
||||
Q(languages=[]) | Q(languages__contains=["English"]),
|
||||
**filters,
|
||||
**null_fields
|
||||
)
|
||||
.annotate(Count("parent_work__editions"))
|
||||
.filter(
|
||||
# mustn't be the only edition for the work
|
||||
parent_work__editions__count__gt=1
|
||||
)
|
||||
)
|
||||
print(editions.count())
|
||||
editions.delete()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
''' dedplucate allllll the book data models '''
|
||||
help = 'merges duplicate book data'
|
||||
""" dedplucate allllll the book data models """
|
||||
|
||||
help = "merges duplicate book data"
|
||||
# pylint: disable=no-self-use,unused-argument
|
||||
def handle(self, *args, **options):
|
||||
''' run deudplications '''
|
||||
""" run deudplications """
|
||||
remove_editions()
|
||||
|
Reference in New Issue
Block a user