Handle genres and authors casing

This commit is contained in:
2026-03-31 13:31:50 +02:00
parent 39fb2edd71
commit da0924eb41
5 changed files with 18 additions and 16 deletions

View File

@@ -380,7 +380,7 @@ def list_books(
click.echo("-" * 75) click.echo("-" * 75)
for book in books: for book in books:
authors_str = ", ".join(a.name for a in book.authors)[:22] authors_str = ", ".join(a.name.title() for a in book.authors)[:22]
if len(authors_str) == 22: if len(authors_str) == 22:
authors_str += "..." authors_str += "..."
owner_str = book.owner.username if book.owner else "" owner_str = book.owner.username if book.owner else ""
@@ -459,7 +459,7 @@ def search_books(
click.echo("-" * 72) click.echo("-" * 72)
for book in books: for book in books:
authors_str = ", ".join(a.name for a in book.authors)[:27] authors_str = ", ".join(a.name.title() for a in book.authors)[:27]
if len(authors_str) == 27: if len(authors_str) == 27:
authors_str += "..." authors_str += "..."
click.echo(f"{book.id:<4} {book.title[:32]:<35} {authors_str:<30}") click.echo(f"{book.id:<4} {book.title[:32]:<35} {authors_str:<30}")
@@ -502,7 +502,7 @@ def import_book(
fetch_cover=not no_cover, fetch_cover=not no_cover,
) )
click.echo( click.echo(
f"Imported book: {book.title} by {', '.join(a.name for a in book.authors)} (ID: {book.id})" f"Imported book: {book.title} by {', '.join(a.name.title() for a in book.authors)} (ID: {book.id})"
) )
except Exception as e: except Exception as e:
click.echo(f"Error importing book: {e}", err=True) click.echo(f"Error importing book: {e}", err=True)

View File

@@ -645,13 +645,14 @@ def get_books_by_location(
def _get_or_create_author(name: str) -> Author: def _get_or_create_author(name: str) -> Author:
"""Get existing author or create a new one.""" """Get existing author or create a new one. Always store as lowercase."""
normalized = name.strip().lower()
author = db.session.execute( author = db.session.execute(
select(Author).filter(Author.name == name) select(Author).filter(Author.name == normalized)
).scalar_one_or_none() ).scalar_one_or_none()
if author is None: if author is None:
author = Author(name=name) author = Author(name=normalized)
db.session.add(author) db.session.add(author)
# Don't commit here - let the caller handle the transaction # Don't commit here - let the caller handle the transaction
@@ -659,13 +660,14 @@ def _get_or_create_author(name: str) -> Author:
def _get_or_create_genre(name: str) -> Genre: def _get_or_create_genre(name: str) -> Genre:
"""Get existing genre or create a new one.""" """Get existing genre or create a new one. Always store as lowercase."""
normalized = name.strip().lower()
genre = db.session.execute( genre = db.session.execute(
select(Genre).filter(Genre.name == name) select(Genre).filter(Genre.name == normalized)
).scalar_one_or_none() ).scalar_one_or_none()
if genre is None: if genre is None:
genre = Genre(name=name) genre = Genre(name=normalized)
db.session.add(genre) db.session.add(genre)
# Don't commit here - let the caller handle the transaction # Don't commit here - let the caller handle the transaction

View File

@@ -22,7 +22,7 @@
<div class="bg-light p-3 rounded mb-4"> <div class="bg-light p-3 rounded mb-4">
<h6 class="fw-bold">{{ book.title }}</h6> <h6 class="fw-bold">{{ book.title }}</h6>
{% if book.authors %} {% if book.authors %}
<p class="text-muted small mb-1">by {{ book.authors | join(', ') }}</p> <p class="text-muted small mb-1">by {{ book.authors | map('title') | join(', ') }}</p>
{% endif %} {% endif %}
{% if book.isbn %} {% if book.isbn %}
<p class="text-muted small mb-0">ISBN: {{ book.isbn }}</p> <p class="text-muted small mb-0">ISBN: {{ book.isbn }}</p>

View File

@@ -45,7 +45,7 @@
{% if book.authors %} {% if book.authors %}
<p class="card-text text-muted small text-truncate mb-2"> <p class="card-text text-muted small text-truncate mb-2">
by {{ book.authors | join(', ') }} by {{ book.authors | map('title') | join(', ') }}
</p> </p>
{% endif %} {% endif %}
@@ -63,7 +63,7 @@
{% if book.genres %} {% if book.genres %}
<div class="mt-1"> <div class="mt-1">
{% for genre in book.genres[:2] %} {% for genre in book.genres[:2] %}
<span class="badge bg-light text-dark small me-1">{{ genre }}</span> <span class="badge bg-light text-dark small me-1">{{ genre|title }}</span>
{% endfor %} {% endfor %}
{% if book.genres|length > 2 %} {% if book.genres|length > 2 %}
<span class="badge bg-light text-dark small">+{{ book.genres|length - 2 }}</span> <span class="badge bg-light text-dark small">+{{ book.genres|length - 2 }}</span>

View File

@@ -21,12 +21,12 @@
<div class="col-md-6"> <div class="col-md-6">
<label for="authors" class="form-label">Authors</label> <label for="authors" class="form-label">Authors</label>
<textarea class="form-control" id="authors" name="authors" rows="2" <textarea class="form-control" id="authors" name="authors" rows="2"
placeholder="One author per line">{% if book and book.authors %}{{ book.authors | join('\n') }}{% endif %}</textarea> placeholder="One author per line">{% if book and book.authors %}{{ book.authors | map('title') | join('\n') }}{% endif %}</textarea>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<label for="genres" class="form-label">Genres</label> <label for="genres" class="form-label">Genres</label>
<textarea class="form-control" id="genres" name="genres" rows="2" <textarea class="form-control" id="genres" name="genres" rows="2"
placeholder="One genre per line">{% if book and book.genres %}{{ book.genres | join('\n') }}{% endif %}</textarea> placeholder="One genre per line">{% if book and book.genres %}{{ book.genres | map('title') | join('\n') }}{% endif %}</textarea>
</div> </div>
</div> </div>
@@ -155,12 +155,12 @@
}; };
new Tagify(document.querySelector('#genres'), { new Tagify(document.querySelector('#genres'), {
...commmon_settings, ...commmon_settings,
whitelist: {{ genres | map(attribute = 'name') | list | pprint }}, whitelist: {{ genres | map(attribute = 'name') | map('title') | list | pprint }},
dropdown: { enabled: 0, closeOnSelect: false } dropdown: { enabled: 0, closeOnSelect: false }
}); });
new Tagify(document.querySelector('#authors'), { new Tagify(document.querySelector('#authors'), {
...commmon_settings, ...commmon_settings,
whitelist: {{ authors | map(attribute = 'name') | list | pprint }}, whitelist: {{ authors | map(attribute = 'name') | map('title') | list | pprint }},
dropdown: { enabled: 0, closeOnSelect: false } dropdown: { enabled: 0, closeOnSelect: false }
}); });
</script> </script>