forked from mirrors/bookwyrm
commit
ad9008ada8
9 changed files with 92 additions and 12 deletions
|
@ -41,6 +41,7 @@ class Edition(Book):
|
||||||
pages: int = None
|
pages: int = None
|
||||||
physicalFormat: str = ''
|
physicalFormat: str = ''
|
||||||
publishers: List[str] = field(default_factory=lambda: [])
|
publishers: List[str] = field(default_factory=lambda: [])
|
||||||
|
editionRank: int = 0
|
||||||
|
|
||||||
type: str = 'Edition'
|
type: str = 'Edition'
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,11 @@ class Connector(AbstractMinimalConnector):
|
||||||
''' this is basically just for search '''
|
''' this is basically just for search '''
|
||||||
|
|
||||||
def get_or_create_book(self, remote_id):
|
def get_or_create_book(self, remote_id):
|
||||||
return activitypub.resolve_remote_id(models.Edition, remote_id)
|
edition = activitypub.resolve_remote_id(models.Edition, remote_id)
|
||||||
|
work = edition.parent_work
|
||||||
|
work.default_edition = work.get_default_edition()
|
||||||
|
work.save()
|
||||||
|
return edition
|
||||||
|
|
||||||
def parse_search_data(self, data):
|
def parse_search_data(self, data):
|
||||||
return data
|
return data
|
||||||
|
|
27
bookwyrm/migrations/0035_edition_edition_rank.py
Normal file
27
bookwyrm/migrations/0035_edition_edition_rank.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Generated by Django 3.0.7 on 2021-01-11 17:18
|
||||||
|
|
||||||
|
import bookwyrm.models.fields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def set_rank(app_registry, schema_editor):
|
||||||
|
db_alias = schema_editor.connection.alias
|
||||||
|
books = app_registry.get_model('bookwyrm', 'Edition')
|
||||||
|
for book in books.objects.using(db_alias):
|
||||||
|
book.edition_rank = book.get_rank
|
||||||
|
book.save()
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bookwyrm', '0034_importjob_complete'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='edition',
|
||||||
|
name='edition_rank',
|
||||||
|
field=bookwyrm.models.fields.IntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.RunPython(set_rank),
|
||||||
|
]
|
|
@ -52,10 +52,11 @@ def execute_after_save(sender, instance, created, *args, **kwargs):
|
||||||
instance.save()
|
instance.save()
|
||||||
|
|
||||||
|
|
||||||
def unfurl_related_field(related_field):
|
def unfurl_related_field(related_field, sort_field=None):
|
||||||
''' load reverse lookups (like public key owner or Status attachment '''
|
''' load reverse lookups (like public key owner or Status attachment '''
|
||||||
if hasattr(related_field, 'all'):
|
if hasattr(related_field, 'all'):
|
||||||
return [unfurl_related_field(i) for i in related_field.all()]
|
return [unfurl_related_field(i) for i in related_field.order_by(
|
||||||
|
sort_field).all()]
|
||||||
if related_field.reverse_unfurl:
|
if related_field.reverse_unfurl:
|
||||||
return related_field.field_to_activity()
|
return related_field.field_to_activity()
|
||||||
return related_field.remote_id
|
return related_field.remote_id
|
||||||
|
@ -145,11 +146,11 @@ class ActivitypubMixin:
|
||||||
|
|
||||||
if hasattr(self, 'serialize_reverse_fields'):
|
if hasattr(self, 'serialize_reverse_fields'):
|
||||||
# for example, editions of a work
|
# for example, editions of a work
|
||||||
for model_field_name, activity_field_name in \
|
for model_field_name, activity_field_name, sort_field in \
|
||||||
self.serialize_reverse_fields:
|
self.serialize_reverse_fields:
|
||||||
related_field = getattr(self, model_field_name)
|
related_field = getattr(self, model_field_name)
|
||||||
activity[activity_field_name] = \
|
activity[activity_field_name] = \
|
||||||
unfurl_related_field(related_field)
|
unfurl_related_field(related_field, sort_field)
|
||||||
|
|
||||||
if not activity.get('id'):
|
if not activity.get('id'):
|
||||||
activity['id'] = self.get_remote_id()
|
activity['id'] = self.get_remote_id()
|
||||||
|
|
|
@ -122,20 +122,29 @@ class Work(OrderedCollectionPageMixin, Book):
|
||||||
load_remote=False
|
load_remote=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
''' set some fields on the edition object '''
|
||||||
|
# set rank
|
||||||
|
for edition in self.editions.all():
|
||||||
|
edition.save()
|
||||||
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
def get_default_edition(self):
|
def get_default_edition(self):
|
||||||
''' in case the default edition is not set '''
|
''' in case the default edition is not set '''
|
||||||
return self.default_edition or self.editions.first()
|
return self.default_edition or self.editions.order_by(
|
||||||
|
'-edition_rank'
|
||||||
|
).first()
|
||||||
|
|
||||||
def to_edition_list(self, **kwargs):
|
def to_edition_list(self, **kwargs):
|
||||||
''' an ordered collection of editions '''
|
''' an ordered collection of editions '''
|
||||||
return self.to_ordered_collection(
|
return self.to_ordered_collection(
|
||||||
self.editions.order_by('-updated_date').all(),
|
self.editions.order_by('-edition_rank').all(),
|
||||||
remote_id='%s/editions' % self.remote_id,
|
remote_id='%s/editions' % self.remote_id,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
activity_serializer = activitypub.Work
|
activity_serializer = activitypub.Work
|
||||||
serialize_reverse_fields = [('editions', 'editions')]
|
serialize_reverse_fields = [('editions', 'editions', '-edition_rank')]
|
||||||
deserialize_reverse_fields = [('editions', 'editions')]
|
deserialize_reverse_fields = [('editions', 'editions')]
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,17 +173,39 @@ class Edition(Book):
|
||||||
parent_work = fields.ForeignKey(
|
parent_work = fields.ForeignKey(
|
||||||
'Work', on_delete=models.PROTECT, null=True,
|
'Work', on_delete=models.PROTECT, null=True,
|
||||||
related_name='editions', activitypub_field='work')
|
related_name='editions', activitypub_field='work')
|
||||||
|
edition_rank = fields.IntegerField(default=0)
|
||||||
|
|
||||||
activity_serializer = activitypub.Edition
|
activity_serializer = activitypub.Edition
|
||||||
name_field = 'title'
|
name_field = 'title'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def get_rank(self):
|
||||||
|
''' calculate how complete the data is on this edition '''
|
||||||
|
if self.parent_work and self.parent_work.default_edition == self:
|
||||||
|
# default edition has the highest rank
|
||||||
|
return 20
|
||||||
|
rank = 0
|
||||||
|
rank += int(bool(self.cover)) * 3
|
||||||
|
rank += int(bool(self.isbn_13))
|
||||||
|
rank += int(bool(self.isbn_10))
|
||||||
|
rank += int(bool(self.oclc_number))
|
||||||
|
rank += int(bool(self.pages))
|
||||||
|
rank += int(bool(self.physical_format))
|
||||||
|
rank += int(bool(self.description))
|
||||||
|
# max rank is 9
|
||||||
|
return rank
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
''' calculate isbn 10/13 '''
|
''' set some fields on the edition object '''
|
||||||
|
# calculate isbn 10/13
|
||||||
if self.isbn_13 and self.isbn_13[:3] == '978' and not self.isbn_10:
|
if self.isbn_13 and self.isbn_13[:3] == '978' and not self.isbn_10:
|
||||||
self.isbn_10 = isbn_13_to_10(self.isbn_13)
|
self.isbn_10 = isbn_13_to_10(self.isbn_13)
|
||||||
if self.isbn_10 and not self.isbn_13:
|
if self.isbn_10 and not self.isbn_13:
|
||||||
self.isbn_13 = isbn_10_to_13(self.isbn_10)
|
self.isbn_13 = isbn_10_to_13(self.isbn_10)
|
||||||
|
|
||||||
|
# set rank
|
||||||
|
self.edition_rank = self.get_rank
|
||||||
|
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
|
||||||
objects = InheritanceManager()
|
objects = InheritanceManager()
|
||||||
|
|
||||||
activity_serializer = activitypub.Note
|
activity_serializer = activitypub.Note
|
||||||
serialize_reverse_fields = [('attachments', 'attachment')]
|
serialize_reverse_fields = [('attachments', 'attachment', 'id')]
|
||||||
deserialize_reverse_fields = [('attachments', 'attachment')]
|
deserialize_reverse_fields = [('attachments', 'attachment')]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -200,7 +200,7 @@ class KeyPair(ActivitypubMixin, BookWyrmModel):
|
||||||
blank=True, null=True, activitypub_field='publicKeyPem')
|
blank=True, null=True, activitypub_field='publicKeyPem')
|
||||||
|
|
||||||
activity_serializer = activitypub.PublicKey
|
activity_serializer = activitypub.PublicKey
|
||||||
serialize_reverse_fields = [('owner', 'owner')]
|
serialize_reverse_fields = [('owner', 'owner', 'id')]
|
||||||
|
|
||||||
def get_remote_id(self):
|
def get_remote_id(self):
|
||||||
# self.owner is set by the OneToOneField on User
|
# self.owner is set by the OneToOneField on User
|
||||||
|
|
|
@ -82,3 +82,19 @@ class Book(TestCase):
|
||||||
self.assertEqual(book.edition_info, 'worm, Glorbish language, 2020')
|
self.assertEqual(book.edition_info, 'worm, Glorbish language, 2020')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
book.alt_text, 'Test Edition cover (worm, Glorbish language, 2020)')
|
book.alt_text, 'Test Edition cover (worm, Glorbish language, 2020)')
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_rank(self):
|
||||||
|
''' sets the data quality index for the book '''
|
||||||
|
# basic rank
|
||||||
|
self.assertEqual(self.first_edition.edition_rank, 0)
|
||||||
|
|
||||||
|
self.first_edition.description = 'hi'
|
||||||
|
self.first_edition.save()
|
||||||
|
self.assertEqual(self.first_edition.edition_rank, 1)
|
||||||
|
|
||||||
|
# default edition
|
||||||
|
self.work.default_edition = self.first_edition
|
||||||
|
self.work.save()
|
||||||
|
self.first_edition.refresh_from_db()
|
||||||
|
self.assertEqual(self.first_edition.edition_rank, 20)
|
||||||
|
|
|
@ -736,7 +736,7 @@ def editions_page(request, book_id):
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'title': 'Editions of %s' % work.title,
|
'title': 'Editions of %s' % work.title,
|
||||||
'editions': work.editions.all(),
|
'editions': work.editions.order_by('-edition_rank').all(),
|
||||||
'work': work,
|
'work': work,
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, 'editions.html', data)
|
return TemplateResponse(request, 'editions.html', data)
|
||||||
|
|
Loading…
Reference in a new issue