From 46e38366c701087657ea67f0844a353ea8882e96 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 10 Feb 2020 21:09:04 -0800 Subject: [PATCH] Stores book identifiers with path part --- fedireads/openlibrary.py | 31 +++++++++++++++++++-------- fedireads/templates/book.html | 6 +----- fedireads/templates/book_results.html | 2 +- fedireads/templates/book_snippet.html | 14 ++++++++++++ fedireads/templates/feed.html | 31 +++++---------------------- fedireads/urls.py | 2 +- fedireads/views.py | 4 ++-- rebuilddb.sh | 4 ++-- 8 files changed, 48 insertions(+), 46 deletions(-) create mode 100644 fedireads/templates/book_snippet.html diff --git a/fedireads/openlibrary.py b/fedireads/openlibrary.py index d22046bc0..6fe100358 100644 --- a/fedireads/openlibrary.py +++ b/fedireads/openlibrary.py @@ -1,6 +1,7 @@ ''' activitystream api and books ''' from django.core.exceptions import ObjectDoesNotExist from django.core.files.base import ContentFile +import re import requests from fedireads.models import Author, Book @@ -14,10 +15,13 @@ def book_search(query): response.raise_for_status() data = response.json() results = [] + for doc in data['docs'][:5]: + key = doc['key'] + key = key.split('/')[-1] results.append({ 'title': doc['title'], - 'olkey': doc['key'], + 'olkey': key, 'year': doc['first_publish_year'], 'author': doc['author_name'][0], }) @@ -25,9 +29,13 @@ def book_search(query): def get_or_create_book(olkey, user=None, update=False): - ''' add a book ''' - # TODO: check if this is a valid open library key, and a work - olkey = olkey + ''' add a book by looking up its open library "work" key. I'm conflating + "book" and "work" here a bit; the table is called "book" in fedireads, but + in open library parlance, it's a "work," which is the canonical umbrella + item that contains all the editions ("book"s) ''' + # check if this is in the format of an OL book identifier + if not re.match(r'^OL\d+W$', olkey): + raise ValueError('Invalid OpenLibrary work ID') # get the existing entry from our db, if it exists try: @@ -40,7 +48,7 @@ def get_or_create_book(olkey, user=None, update=False): book = Book(openlibrary_key=olkey) # load the book json from openlibrary.org - response = requests.get(OL_URL + olkey + '.json') + response = requests.get('%s/works/%s.json' % (OL_URL, olkey)) if not response.ok: response.raise_for_status() @@ -55,10 +63,12 @@ def get_or_create_book(olkey, user=None, update=False): # we also need to know the author get the cover for author_blob in data['authors']: + # this id starts as "/authors/OL1234567A" and we want just "OL1234567A" author_id = author_blob['author']['key'] + author_id = author_id.split('/')[-1] book.authors.add(get_or_create_author(author_id)) - if len(data['covers']): + if data['covers'] and len(data['covers']): book.cover.save(*get_cover(data['covers'][0]), save=True) return book @@ -76,15 +86,18 @@ def get_cover(cover_id): return [image_name, image_content] -def get_or_create_author(olkey): +def get_or_create_author(olkey, update=False): ''' load that author ''' - # TODO: validate that this is an author key + if not re.match(r'^OL\d+A$', olkey): + raise ValueError('Invalid OpenLibrary author ID') try: author = Author.objects.get(openlibrary_key=olkey) + if not update: + return author except ObjectDoesNotExist: pass - response = requests.get(OL_URL + olkey + '.json') + response = requests.get('%s/authors/%s.json' % (OL_URL, olkey)) if not response.ok: response.raise_for_status() diff --git a/fedireads/templates/book.html b/fedireads/templates/book.html index bb76cc5fb..2f2a33844 100644 --- a/fedireads/templates/book.html +++ b/fedireads/templates/book.html @@ -4,11 +4,7 @@
- -

{{ book.data.title }}

- by {{ book.authors.first.data.name }} - {{ rating | stars }} {{ rating }} -
{{ book.data.description | description }}
+ {% include 'book_snippet.html' with book=book size=large rating=rating description=True %}
diff --git a/fedireads/templates/book_results.html b/fedireads/templates/book_results.html index d85eb7bde..be2ee35b9 100644 --- a/fedireads/templates/book_results.html +++ b/fedireads/templates/book_results.html @@ -5,7 +5,7 @@

Search results

{% for result in results %}
- {{ result.title }} by {{ result.author }} ({{ result.year }}) + {{ result.title }} by {{ result.author }} ({{ result.year }})
{% endfor %}
diff --git a/fedireads/templates/book_snippet.html b/fedireads/templates/book_snippet.html new file mode 100644 index 000000000..25259b6ad --- /dev/null +++ b/fedireads/templates/book_snippet.html @@ -0,0 +1,14 @@ +{% load fr_display %} + +

+ {{ book.data.title }} +

+

by {{ book.authors.first.data.name }}

+ +{% if rating %} +{{ rating | stars }} {{ rating }} +{% endif %} + +{% if description %} +
{{ book.data.description | description }}
+{% endif %} diff --git a/fedireads/templates/feed.html b/fedireads/templates/feed.html index ffbb2b830..d9db63b8e 100644 --- a/fedireads/templates/feed.html +++ b/fedireads/templates/feed.html @@ -9,9 +9,7 @@

Start a book!

{% for book in to_read.books.all %}
- -

{{ book.data.title }}

-

by {{ book.authors.first.data.name }}

+ {% include 'book_snippet.html' with book=book size="small" %}
{% csrf_token %} @@ -23,9 +21,7 @@ {% for book in reading.books.all %}
- -

{{ book.data.title }}

-

by {{ book.authors.first.data.name }}

+ {% include 'book_snippet.html' with book=book size="small" %} {% csrf_token %} @@ -39,13 +35,7 @@

Recently Added Books

{% for book in recent_books %}
- -

- {{ book.data.title }} - by - {# TODO: there should be a helper function for listing authors #} - {{ book.authors.first.data.name }} -

+ {% include 'book_snippet.html' with book=book size="small" %} {% if not book in user_books.all %} {% csrf_token %} @@ -81,13 +71,7 @@ {# TODO: wouldn't it rule if this was a reusable piece of markup? #}
- -

- {{ activity.book.data.title }} - by - {{ activity.book.authors.first.data.name }} -

{{ activity.book.data.description | description }}
-

+ {% include 'book_snippet.html' with book=activity.book size=large description=True %}
{% elif activity.fedireads_type == 'Review' %} @@ -95,12 +79,7 @@ reviewed {{ activity.book.data.title }}
- -

- {{ activity.book.data.title }} - by - {{ activity.book.authors.first.data.name }} -

+ {% include 'book_snippet.html' with book=activity.book size=large %}

{{ activity.name }}

{{ activity.rating | stars }}

diff --git a/fedireads/urls.py b/fedireads/urls.py index a44fefcf3..390f6e63a 100644 --- a/fedireads/urls.py +++ b/fedireads/urls.py @@ -28,7 +28,7 @@ urlpatterns = [ # this endpoint is both ui and fed depending on Accept type re_path(r'^user/(?P[\w@\.]+)/?$', views.user_profile), re_path(r'^user/(?P\w+)/edit/?$', views.user_profile_edit), - re_path(r'^work/(?P\w+)/?$', views.book_page), + re_path(r'^book/(?P\w+)/?$', views.book_page), # internal action endpoints re_path(r'^review/?$', views.review), diff --git a/fedireads/views.py b/fedireads/views.py index ad3ea602e..f3edf606d 100644 --- a/fedireads/views.py +++ b/fedireads/views.py @@ -178,7 +178,7 @@ def edit_profile(request): @login_required def book_page(request, book_identifier): ''' info about a book ''' - book = openlibrary.get_or_create_book('/work/' + book_identifier) + book = openlibrary.get_or_create_book(book_identifier) # TODO: again, post privacy? reviews = models.Review.objects.filter(book=book) rating = reviews.aggregate(Avg('rating')) @@ -226,7 +226,7 @@ def review(request): rating = form.data.get('rating') outgoing.handle_review(request.user, book, name, content, rating) - return redirect(book_identifier) + return redirect('/book/%s' % book_identifier) @login_required diff --git a/rebuilddb.sh b/rebuilddb.sh index 6ac61b478..446edff0e 100755 --- a/rebuilddb.sh +++ b/rebuilddb.sh @@ -12,6 +12,6 @@ echo "from fedireads.models import User User.objects.create_user('rat', 'rat@rat.com', 'ratword') User.objects.get(id=1).followers.add(User.objects.get(id=2))" | python manage.py shell echo "from fedireads.openlibrary import get_or_create_book -get_or_create_book('/work/OL1715344W') -get_or_create_book('/work/OL102749W')" | python manage.py shell +get_or_create_book('OL1715344W') +get_or_create_book('OL102749W')" | python manage.py shell python manage.py runserver