diff --git a/bookwyrm/forms/books.py b/bookwyrm/forms/books.py index 623beaa04..3a3979e2c 100644 --- a/bookwyrm/forms/books.py +++ b/bookwyrm/forms/books.py @@ -20,6 +20,7 @@ class EditionForm(CustomForm): model = models.Edition fields = [ "title", + "sort_title", "subtitle", "description", "series", @@ -45,6 +46,9 @@ class EditionForm(CustomForm): ] widgets = { "title": forms.TextInput(attrs={"aria-describedby": "desc_title"}), + "sort_title": forms.TextInput( + attrs={"aria-describedby": "desc_sort_title"} + ), "subtitle": forms.TextInput(attrs={"aria-describedby": "desc_subtitle"}), "description": forms.Textarea( attrs={"aria-describedby": "desc_description"} diff --git a/bookwyrm/forms/lists.py b/bookwyrm/forms/lists.py index 647db3bfe..f5008baa3 100644 --- a/bookwyrm/forms/lists.py +++ b/bookwyrm/forms/lists.py @@ -24,7 +24,7 @@ class SortListForm(forms.Form): sort_by = ChoiceField( choices=( ("order", _("List Order")), - ("title", _("Book Title")), + ("sort_title", _("Book Title")), ("rating", _("Rating")), ), label=_("Sort By"), diff --git a/bookwyrm/migrations/0179_populate_sort_title.py b/bookwyrm/migrations/0179_populate_sort_title.py new file mode 100644 index 000000000..e238bca1d --- /dev/null +++ b/bookwyrm/migrations/0179_populate_sort_title.py @@ -0,0 +1,49 @@ +import re +from itertools import chain + +from django.db import migrations, transaction +from django.db.models import Q + +from bookwyrm.settings import LANGUAGE_ARTICLES + + +def set_sort_title(edition): + articles = chain( + *(LANGUAGE_ARTICLES.get(language, ()) for language in tuple(edition.languages)) + ) + edition.sort_title = re.sub( + f'^{" |^".join(articles)} ', "", str(edition.title).lower() + ) + return edition + + +@transaction.atomic +def populate_sort_title(apps, schema_editor): + Edition = apps.get_model("bookwyrm", "Edition") + db_alias = schema_editor.connection.alias + editions_wo_sort_title = Edition.objects.using(db_alias).filter( + Q(sort_title__isnull=True) | Q(sort_title__exact="") + ) + batch_size = 1000 + start = 0 + end = batch_size + while True: + batch = editions_wo_sort_title[start:end] + if not batch.exists(): + break + Edition.objects.bulk_update( + (set_sort_title(edition) for edition in batch), ["sort_title"] + ) + start = end + end += batch_size + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0178_auto_20230328_2132"), + ] + + operations = [ + migrations.RunPython(populate_sort_title), + ] diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index 4e7ffcad3..c25f8fee2 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -1,4 +1,5 @@ """ database schema for books and shelves """ +from itertools import chain import re from django.contrib.postgres.search import SearchVectorField @@ -17,6 +18,7 @@ from bookwyrm.preview_images import generate_edition_preview_image_task from bookwyrm.settings import ( DOMAIN, DEFAULT_LANGUAGE, + LANGUAGE_ARTICLES, ENABLE_PREVIEW_IMAGES, ENABLE_THUMBNAIL_GENERATION, ) @@ -363,6 +365,19 @@ class Edition(Book): for author_id in self.authors.values_list("id", flat=True): cache.delete(f"author-books-{author_id}") + # Create sort title by removing articles from title + if self.sort_title in [None, ""]: + if self.sort_title in [None, ""]: + articles = chain( + *( + LANGUAGE_ARTICLES.get(language, ()) + for language in tuple(self.languages) + ) + ) + self.sort_title = re.sub( + f'^{" |^".join(articles)} ', "", str(self.title).lower() + ) + return super().save(*args, **kwargs) @classmethod diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index d75b06cf8..ae5a6a57f 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -312,6 +312,9 @@ LANGUAGES = [ ("zh-hant", _("繁體中文 (Traditional Chinese)")), ] +LANGUAGE_ARTICLES = { + "English": {"the", "a", "an"}, +} TIME_ZONE = "UTC" diff --git a/bookwyrm/templates/book/edit/edit_book_form.html b/bookwyrm/templates/book/edit/edit_book_form.html index e85164444..72d80e9cf 100644 --- a/bookwyrm/templates/book/edit/edit_book_form.html +++ b/bookwyrm/templates/book/edit/edit_book_form.html @@ -28,6 +28,15 @@ {% include 'snippets/form_errors.html' with errors_list=form.title.errors id="desc_title" %} +
+ + + + {% include 'snippets/form_errors.html' with errors_list=form.sort_title.errors id="desc_sort_title" %} +
+