Merge pull request #1221 from cincodenada/shelved-date

Add shelved date, populate from Goodreads import
This commit is contained in:
Mouse Reeve 2021-07-19 17:11:22 -06:00 committed by GitHub
commit b84ffeda08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 55 deletions

View File

@ -2,6 +2,8 @@
import csv import csv
import logging import logging
from django.utils import timezone
from bookwyrm import models from bookwyrm import models
from bookwyrm.models import ImportJob, ImportItem from bookwyrm.models import ImportJob, ImportItem
from bookwyrm.tasks import app from bookwyrm.tasks import app
@ -100,7 +102,10 @@ def handle_imported_book(source, user, item, include_reviews, privacy):
# shelve the book if it hasn't been shelved already # shelve the book if it hasn't been shelved already
if item.shelf and not existing_shelf: if item.shelf and not existing_shelf:
desired_shelf = models.Shelf.objects.get(identifier=item.shelf, user=user) desired_shelf = models.Shelf.objects.get(identifier=item.shelf, user=user)
models.ShelfBook.objects.create(book=item.book, shelf=desired_shelf, user=user) shelved_date = item.date_added or timezone.now()
models.ShelfBook.objects.create(
book=item.book, shelf=desired_shelf, user=user, shelved_date=shelved_date
)
for read in item.reads: for read in item.reads:
# check for an existing readthrough with the same dates # check for an existing readthrough with the same dates

View File

@ -0,0 +1,34 @@
# Generated by Django 3.2.4 on 2021-07-03 08:25
from django.db import migrations, models
import django.utils.timezone
def copy_created_date(app_registry, schema_editor):
db_alias = schema_editor.connection.alias
ShelfBook = app_registry.get_model("bookwyrm", "ShelfBook")
ShelfBook.objects.all().update(shelved_date=models.F("created_date"))
def do_nothing(app_registry, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0077_auto_20210623_2155"),
]
operations = [
migrations.AlterModelOptions(
name="shelfbook",
options={"ordering": ("-shelved_date",)},
),
migrations.AddField(
model_name="shelfbook",
name="shelved_date",
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.RunPython(copy_created_date, reverse_code=do_nothing),
]

View File

@ -1,6 +1,7 @@
""" puttin' books on shelves """ """ puttin' books on shelves """
import re import re
from django.db import models from django.db import models
from django.utils import timezone
from bookwyrm import activitypub from bookwyrm import activitypub
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
@ -69,6 +70,7 @@ class ShelfBook(CollectionItemMixin, BookWyrmModel):
"Edition", on_delete=models.PROTECT, activitypub_field="book" "Edition", on_delete=models.PROTECT, activitypub_field="book"
) )
shelf = models.ForeignKey("Shelf", on_delete=models.PROTECT) shelf = models.ForeignKey("Shelf", on_delete=models.PROTECT)
shelved_date = models.DateTimeField(default=timezone.now)
user = fields.ForeignKey( user = fields.ForeignKey(
"User", on_delete=models.PROTECT, activitypub_field="actor" "User", on_delete=models.PROTECT, activitypub_field="actor"
) )
@ -86,4 +88,4 @@ class ShelfBook(CollectionItemMixin, BookWyrmModel):
you can't put a book on shelf twice""" you can't put a book on shelf twice"""
unique_together = ("book", "shelf") unique_together = ("book", "shelf")
ordering = ("-created_date",) ordering = ("-shelved_date", "-created_date", "-updated_date")

View File

@ -103,7 +103,7 @@
{% include 'snippets/authors.html' %} {% include 'snippets/authors.html' %}
</td> </td>
<td data-title="{% trans "Shelved" %}"> <td data-title="{% trans "Shelved" %}">
{{ book.created_date|naturalday }} {{ book.shelved_date|naturalday }}
</td> </td>
{% latest_read_through book user as read_through %} {% latest_read_through book user as read_through %}
<td data-title="{% trans "Started" %}"> <td data-title="{% trans "Started" %}">

View File

@ -3,6 +3,8 @@ from collections import namedtuple
import csv import csv
import pathlib import pathlib
from unittest.mock import patch from unittest.mock import patch
import datetime
import pytz
from django.test import TestCase from django.test import TestCase
import responses import responses
@ -13,6 +15,10 @@ from bookwyrm.importers.importer import import_data, handle_imported_book
from bookwyrm.settings import DOMAIN from bookwyrm.settings import DOMAIN
def make_date(*args):
return datetime.datetime(*args, tzinfo=pytz.UTC)
class GoodreadsImport(TestCase): class GoodreadsImport(TestCase):
"""importing from goodreads csv""" """importing from goodreads csv"""
@ -130,22 +136,25 @@ class GoodreadsImport(TestCase):
shelf.refresh_from_db() shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book) self.assertEqual(shelf.books.first(), self.book)
self.assertEqual(
shelf.shelfbook_set.first().shelved_date, make_date(2020, 10, 21)
)
readthrough = models.ReadThrough.objects.get(user=self.user) readthrough = models.ReadThrough.objects.get(user=self.user)
self.assertEqual(readthrough.book, self.book) self.assertEqual(readthrough.book, self.book)
# I can't remember how to create dates and I don't want to look it up. self.assertEqual(readthrough.start_date, make_date(2020, 10, 21))
self.assertEqual(readthrough.start_date.year, 2020) self.assertEqual(readthrough.finish_date, make_date(2020, 10, 25))
self.assertEqual(readthrough.start_date.month, 10)
self.assertEqual(readthrough.start_date.day, 21)
self.assertEqual(readthrough.finish_date.year, 2020)
self.assertEqual(readthrough.finish_date.month, 10)
self.assertEqual(readthrough.finish_date.day, 25)
def test_handle_imported_book_already_shelved(self): def test_handle_imported_book_already_shelved(self):
"""goodreads import added a book, this adds related connections""" """goodreads import added a book, this adds related connections"""
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
shelf = self.user.shelf_set.filter(identifier="to-read").first() shelf = self.user.shelf_set.filter(identifier="to-read").first()
models.ShelfBook.objects.create(shelf=shelf, user=self.user, book=self.book) models.ShelfBook.objects.create(
shelf=shelf,
user=self.user,
book=self.book,
shelved_date=make_date(2020, 2, 2),
)
import_job = models.ImportJob.objects.create(user=self.user) import_job = models.ImportJob.objects.create(user=self.user)
datafile = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv") datafile = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv")
@ -164,15 +173,15 @@ class GoodreadsImport(TestCase):
shelf.refresh_from_db() shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book) self.assertEqual(shelf.books.first(), self.book)
self.assertEqual(
shelf.shelfbook_set.first().shelved_date, make_date(2020, 2, 2)
)
self.assertIsNone(self.user.shelf_set.get(identifier="read").books.first()) self.assertIsNone(self.user.shelf_set.get(identifier="read").books.first())
readthrough = models.ReadThrough.objects.get(user=self.user) readthrough = models.ReadThrough.objects.get(user=self.user)
self.assertEqual(readthrough.book, self.book) self.assertEqual(readthrough.book, self.book)
self.assertEqual(readthrough.start_date.year, 2020) self.assertEqual(readthrough.start_date, make_date(2020, 10, 21))
self.assertEqual(readthrough.start_date.month, 10) self.assertEqual(readthrough.finish_date, make_date(2020, 10, 25))
self.assertEqual(readthrough.start_date.day, 21)
self.assertEqual(readthrough.finish_date.year, 2020)
self.assertEqual(readthrough.finish_date.month, 10)
self.assertEqual(readthrough.finish_date.day, 25)
def test_handle_import_twice(self): def test_handle_import_twice(self):
"""re-importing books""" """re-importing books"""
@ -198,16 +207,14 @@ class GoodreadsImport(TestCase):
shelf.refresh_from_db() shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book) self.assertEqual(shelf.books.first(), self.book)
self.assertEqual(
shelf.shelfbook_set.first().shelved_date, make_date(2020, 10, 21)
)
readthrough = models.ReadThrough.objects.get(user=self.user) readthrough = models.ReadThrough.objects.get(user=self.user)
self.assertEqual(readthrough.book, self.book) self.assertEqual(readthrough.book, self.book)
# I can't remember how to create dates and I don't want to look it up. self.assertEqual(readthrough.start_date, make_date(2020, 10, 21))
self.assertEqual(readthrough.start_date.year, 2020) self.assertEqual(readthrough.finish_date, make_date(2020, 10, 25))
self.assertEqual(readthrough.start_date.month, 10)
self.assertEqual(readthrough.start_date.day, 21)
self.assertEqual(readthrough.finish_date.year, 2020)
self.assertEqual(readthrough.finish_date.month, 10)
self.assertEqual(readthrough.finish_date.day, 25)
@patch("bookwyrm.activitystreams.ActivityStream.add_status") @patch("bookwyrm.activitystreams.ActivityStream.add_status")
def test_handle_imported_book_review(self, _): def test_handle_imported_book_review(self, _):
@ -229,9 +236,7 @@ class GoodreadsImport(TestCase):
review = models.Review.objects.get(book=self.book, user=self.user) review = models.Review.objects.get(book=self.book, user=self.user)
self.assertEqual(review.content, "mixed feelings") self.assertEqual(review.content, "mixed feelings")
self.assertEqual(review.rating, 2) self.assertEqual(review.rating, 2)
self.assertEqual(review.published_date.year, 2019) self.assertEqual(review.published_date, make_date(2019, 7, 8))
self.assertEqual(review.published_date.month, 7)
self.assertEqual(review.published_date.day, 8)
self.assertEqual(review.privacy, "unlisted") self.assertEqual(review.privacy, "unlisted")
@patch("bookwyrm.activitystreams.ActivityStream.add_status") @patch("bookwyrm.activitystreams.ActivityStream.add_status")
@ -256,9 +261,7 @@ class GoodreadsImport(TestCase):
review = models.ReviewRating.objects.get(book=self.book, user=self.user) review = models.ReviewRating.objects.get(book=self.book, user=self.user)
self.assertIsInstance(review, models.ReviewRating) self.assertIsInstance(review, models.ReviewRating)
self.assertEqual(review.rating, 2) self.assertEqual(review.rating, 2)
self.assertEqual(review.published_date.year, 2019) self.assertEqual(review.published_date, make_date(2019, 7, 8))
self.assertEqual(review.published_date.month, 7)
self.assertEqual(review.published_date.day, 8)
self.assertEqual(review.privacy, "unlisted") self.assertEqual(review.privacy, "unlisted")
def test_handle_imported_book_reviews_disabled(self): def test_handle_imported_book_reviews_disabled(self):

View File

@ -2,6 +2,8 @@
import csv import csv
import pathlib import pathlib
from unittest.mock import patch from unittest.mock import patch
import datetime
import pytz
from django.test import TestCase from django.test import TestCase
import responses import responses
@ -12,6 +14,10 @@ from bookwyrm.importers.importer import import_data, handle_imported_book
from bookwyrm.settings import DOMAIN from bookwyrm.settings import DOMAIN
def make_date(*args):
return datetime.datetime(*args, tzinfo=pytz.UTC)
class LibrarythingImport(TestCase): class LibrarythingImport(TestCase):
"""importing from librarything tsv""" """importing from librarything tsv"""
@ -125,13 +131,8 @@ class LibrarythingImport(TestCase):
readthrough = models.ReadThrough.objects.get(user=self.user) readthrough = models.ReadThrough.objects.get(user=self.user)
self.assertEqual(readthrough.book, self.book) self.assertEqual(readthrough.book, self.book)
# I can't remember how to create dates and I don't want to look it up. self.assertEqual(readthrough.start_date, make_date(2007, 4, 16))
self.assertEqual(readthrough.start_date.year, 2007) self.assertEqual(readthrough.finish_date, make_date(2007, 5, 8))
self.assertEqual(readthrough.start_date.month, 4)
self.assertEqual(readthrough.start_date.day, 16)
self.assertEqual(readthrough.finish_date.year, 2007)
self.assertEqual(readthrough.finish_date.month, 5)
self.assertEqual(readthrough.finish_date.day, 8)
def test_handle_imported_book_already_shelved(self): def test_handle_imported_book_already_shelved(self):
"""librarything import added a book, this adds related connections""" """librarything import added a book, this adds related connections"""
@ -160,14 +161,11 @@ class LibrarythingImport(TestCase):
shelf.refresh_from_db() shelf.refresh_from_db()
self.assertEqual(shelf.books.first(), self.book) self.assertEqual(shelf.books.first(), self.book)
self.assertIsNone(self.user.shelf_set.get(identifier="read").books.first()) self.assertIsNone(self.user.shelf_set.get(identifier="read").books.first())
readthrough = models.ReadThrough.objects.get(user=self.user) readthrough = models.ReadThrough.objects.get(user=self.user)
self.assertEqual(readthrough.book, self.book) self.assertEqual(readthrough.book, self.book)
self.assertEqual(readthrough.start_date.year, 2007) self.assertEqual(readthrough.start_date, make_date(2007, 4, 16))
self.assertEqual(readthrough.start_date.month, 4) self.assertEqual(readthrough.finish_date, make_date(2007, 5, 8))
self.assertEqual(readthrough.start_date.day, 16)
self.assertEqual(readthrough.finish_date.year, 2007)
self.assertEqual(readthrough.finish_date.month, 5)
self.assertEqual(readthrough.finish_date.day, 8)
def test_handle_import_twice(self): def test_handle_import_twice(self):
"""re-importing books""" """re-importing books"""
@ -198,13 +196,8 @@ class LibrarythingImport(TestCase):
readthrough = models.ReadThrough.objects.get(user=self.user) readthrough = models.ReadThrough.objects.get(user=self.user)
self.assertEqual(readthrough.book, self.book) self.assertEqual(readthrough.book, self.book)
# I can't remember how to create dates and I don't want to look it up. self.assertEqual(readthrough.start_date, make_date(2007, 4, 16))
self.assertEqual(readthrough.start_date.year, 2007) self.assertEqual(readthrough.finish_date, make_date(2007, 5, 8))
self.assertEqual(readthrough.start_date.month, 4)
self.assertEqual(readthrough.start_date.day, 16)
self.assertEqual(readthrough.finish_date.year, 2007)
self.assertEqual(readthrough.finish_date.month, 5)
self.assertEqual(readthrough.finish_date.day, 8)
@patch("bookwyrm.activitystreams.ActivityStream.add_status") @patch("bookwyrm.activitystreams.ActivityStream.add_status")
def test_handle_imported_book_review(self, _): def test_handle_imported_book_review(self, _):
@ -226,9 +219,7 @@ class LibrarythingImport(TestCase):
review = models.Review.objects.get(book=self.book, user=self.user) review = models.Review.objects.get(book=self.book, user=self.user)
self.assertEqual(review.content, "chef d'oeuvre") self.assertEqual(review.content, "chef d'oeuvre")
self.assertEqual(review.rating, 5) self.assertEqual(review.rating, 5)
self.assertEqual(review.published_date.year, 2007) self.assertEqual(review.published_date, make_date(2007, 5, 8))
self.assertEqual(review.published_date.month, 5)
self.assertEqual(review.published_date.day, 8)
self.assertEqual(review.privacy, "unlisted") self.assertEqual(review.privacy, "unlisted")
def test_handle_imported_book_reviews_disabled(self): def test_handle_imported_book_reviews_disabled(self):

View File

@ -2,7 +2,7 @@
from collections import namedtuple from collections import namedtuple
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import OuterRef, Subquery from django.db.models import OuterRef, Subquery, F
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.http import HttpResponseBadRequest, HttpResponseNotFound from django.http import HttpResponseBadRequest, HttpResponseNotFound
@ -69,7 +69,8 @@ class Shelf(View):
reviews = privacy_filter(request.user, reviews) reviews = privacy_filter(request.user, reviews)
books = books.annotate( books = books.annotate(
rating=Subquery(reviews.values("rating")[:1]) rating=Subquery(reviews.values("rating")[:1]),
shelved_date=F("shelfbook__shelved_date"),
).prefetch_related("authors") ).prefetch_related("authors")
paginated = Paginator( paginated = Paginator(