Add basic views for books and games
This commit is contained in:
@ -9,7 +9,8 @@ from scrobbles.admin import ScrobbleInline
|
||||
class AuthorAdmin(admin.ModelAdmin):
|
||||
date_hierarchy = "created"
|
||||
list_display = ("name", "openlibrary_id")
|
||||
ordering = ("name",)
|
||||
ordering = ("-created",)
|
||||
search_fields = ("name",)
|
||||
|
||||
|
||||
@admin.register(Book)
|
||||
@ -22,7 +23,8 @@ class BookAdmin(admin.ModelAdmin):
|
||||
"pages",
|
||||
"openlibrary_id",
|
||||
)
|
||||
ordering = ("title",)
|
||||
search_fields = ("name",)
|
||||
ordering = ("-created",)
|
||||
inlines = [
|
||||
ScrobbleInline,
|
||||
]
|
||||
|
||||
@ -61,19 +61,20 @@ def process_koreader_sqlite_file(sqlite_file_path, user_id):
|
||||
logger.debug(f"Found author {author}, created: {created}")
|
||||
|
||||
book, created = Book.objects.get_or_create(
|
||||
koreader_md5=book_row[KoReaderBookColumn.MD5.value]
|
||||
title=book_row[KoReaderBookColumn.TITLE.value]
|
||||
)
|
||||
|
||||
if created:
|
||||
book.title = book_row[KoReaderBookColumn.TITLE.value]
|
||||
book.pages = book_row[KoReaderBookColumn.PAGES.value]
|
||||
book.koreader_md5 = book_row[KoReaderBookColumn.MD5.value]
|
||||
book.koreader_id = int(book_row[KoReaderBookColumn.ID.value])
|
||||
book.koreader_authors = book_row[KoReaderBookColumn.AUTHORS.value]
|
||||
book.run_time_ticks = int(book_row[KoReaderBookColumn.PAGES.value])
|
||||
book.save(
|
||||
update_fields=[
|
||||
"title",
|
||||
"pages",
|
||||
"koreader_md5",
|
||||
"koreader_id",
|
||||
"koreader_authors",
|
||||
]
|
||||
|
||||
@ -30,7 +30,6 @@ class Book(ScrobblableMixin):
|
||||
|
||||
title = models.CharField(max_length=255)
|
||||
authors = models.ManyToManyField(Author)
|
||||
openlibrary_id = models.CharField(max_length=255, **BNULL)
|
||||
goodreads_id = models.CharField(max_length=255, **BNULL)
|
||||
koreader_id = models.IntegerField(**BNULL)
|
||||
koreader_authors = models.CharField(max_length=255, **BNULL)
|
||||
@ -39,6 +38,10 @@ class Book(ScrobblableMixin):
|
||||
pages = models.IntegerField(**BNULL)
|
||||
language = models.CharField(max_length=4, **BNULL)
|
||||
first_publish_year = models.IntegerField(**BNULL)
|
||||
author_name = models.CharField(max_length=255, **BNULL)
|
||||
author_openlibrary_id = models.CharField(max_length=255, **BNULL)
|
||||
openlibrary_id = models.CharField(max_length=255, **BNULL)
|
||||
cover = models.ImageField(upload_to="books/covers/", **BNULL)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.title} by {self.author}"
|
||||
@ -71,3 +74,11 @@ class Book(ScrobblableMixin):
|
||||
user = User.objects.get(id=user_id)
|
||||
last_scrobble = get_scrobbles_for_media(self, user).last()
|
||||
return int((last_scrobble.book_pages_read / self.pages) * 100)
|
||||
|
||||
@classmethod
|
||||
def find_or_create(cls, data_dict: dict) -> "Game":
|
||||
from books.utils import get_or_create_book
|
||||
|
||||
return get_or_create_book(
|
||||
data_dict.get("title"), data_dict.get("author")
|
||||
)
|
||||
|
||||
@ -6,6 +6,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
SEARCH_URL = "https://openlibrary.org/search.json?title={title}"
|
||||
ISBN_URL = "https://openlibrary.org/isbn/{isbn}.json"
|
||||
SEARCH_URL = "https://openlibrary.org/search.json?title={title}"
|
||||
COVER_URL = "https://covers.openlibrary.org/b/olid/{id}-L.jpg"
|
||||
|
||||
|
||||
def get_first(key: str, result: dict) -> str:
|
||||
@ -34,7 +36,7 @@ def lookup_book_from_openlibrary(title: str, author: str = None) -> dict:
|
||||
logger.warn(
|
||||
f"Lookup for {title} found top result with mismatched author"
|
||||
)
|
||||
|
||||
ol_id = top.get("cover_edition_key")
|
||||
return {
|
||||
"title": top.get("title"),
|
||||
"isbn": top.get("isbn")[0],
|
||||
@ -43,4 +45,6 @@ def lookup_book_from_openlibrary(title: str, author: str = None) -> dict:
|
||||
"author_openlibrary_id": get_first("author_key", top),
|
||||
"goodreads_id": get_first("id_goodreads", top),
|
||||
"first_publish_year": top.get("first_publish_year"),
|
||||
"pages": top.get("number_of_pages_median"),
|
||||
"cover_url": COVER_URL.format(id=ol_id),
|
||||
}
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
from django.core.files.base import ContentFile
|
||||
import requests
|
||||
from typing import Optional
|
||||
from books.openlibrary import lookup_book_from_openlibrary
|
||||
from books.models import Book
|
||||
|
||||
|
||||
def get_or_create_book(title: str, author: Optional[str] = None) -> Book:
|
||||
book_dict = lookup_book_from_openlibrary(title, author)
|
||||
|
||||
book, book_created = Book.objects.get_or_create(
|
||||
isbn=book_dict.get("isbn"),
|
||||
)
|
||||
|
||||
if book_created:
|
||||
cover_url = book_dict.pop("cover_url")
|
||||
|
||||
Book.objects.filter(pk=book.id).update(**book_dict)
|
||||
book.refresh_from_db()
|
||||
|
||||
r = requests.get(cover_url)
|
||||
if r.status_code == 200:
|
||||
fname = f"{book.title}_{book.uuid}.jpg"
|
||||
book.cover.save(fname, ContentFile(r.content), save=True)
|
||||
|
||||
book.fix_metadata()
|
||||
|
||||
return book
|
||||
|
||||
Reference in New Issue
Block a user