From 385ec4d70a4f42eaeb1c9e906ec95e4be5eaf024 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 1 Jan 2021 11:05:49 -0800 Subject: [PATCH 01/14] Adds ReviewRating model I can't just calling Rating because that would clash with the rating field --- bookwyrm/activitypub/__init__.py | 3 +- bookwyrm/activitypub/note.py | 16 ++++++-- bookwyrm/forms.py | 4 +- bookwyrm/migrations/0030_reviewrating.py | 52 ++++++++++++++++++++++++ bookwyrm/models/__init__.py | 3 +- bookwyrm/models/status.py | 16 ++++++++ 6 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 bookwyrm/migrations/0030_reviewrating.py diff --git a/bookwyrm/activitypub/__init__.py b/bookwyrm/activitypub/__init__.py index a4fef41e5..49e278bf7 100644 --- a/bookwyrm/activitypub/__init__.py +++ b/bookwyrm/activitypub/__init__.py @@ -6,7 +6,8 @@ from .base_activity import ActivityEncoder, Signature from .base_activity import Link, Mention from .base_activity import ActivitySerializerError, resolve_remote_id from .image import Image -from .note import Note, GeneratedNote, Article, Comment, Review, Quotation +from .note import Note, GeneratedNote, Article, Comment, Quotation +from .note import Review, Rating from .note import Tombstone from .interaction import Boost, Like from .ordered_collection import OrderedCollection, OrderedCollectionPage diff --git a/bookwyrm/activitypub/note.py b/bookwyrm/activitypub/note.py index 72fbe5fc2..cbbeb779f 100644 --- a/bookwyrm/activitypub/note.py +++ b/bookwyrm/activitypub/note.py @@ -50,6 +50,13 @@ class Comment(Note): type: str = 'Comment' +@dataclass(init=False) +class Quotation(Comment): + ''' a quote and commentary on a book ''' + quote: str + type: str = 'Quotation' + + @dataclass(init=False) class Review(Comment): ''' a full book review ''' @@ -59,7 +66,8 @@ class Review(Comment): @dataclass(init=False) -class Quotation(Comment): - ''' a quote and commentary on a book ''' - quote: str - type: str = 'Quotation' +class Rating(Comment): + ''' a full book review ''' + rating: int = None + content: str = None + type: str = 'Rating' diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 686ac8b1d..133f75430 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -54,8 +54,8 @@ class RegisterForm(CustomForm): class RatingForm(CustomForm): class Meta: - model = models.Review - fields = ['user', 'book', 'content', 'rating', 'privacy'] + model = models.ReviewRating + fields = ['user', 'book', 'rating', 'privacy'] class ReviewForm(CustomForm): diff --git a/bookwyrm/migrations/0030_reviewrating.py b/bookwyrm/migrations/0030_reviewrating.py new file mode 100644 index 000000000..3658a666e --- /dev/null +++ b/bookwyrm/migrations/0030_reviewrating.py @@ -0,0 +1,52 @@ +# Generated by Django 3.0.7 on 2021-01-01 19:05 + +from django.db.models.fields.reverse_related import ManyToOneRel +from django.db.models import Q +from django.db import migrations, models +import django.db.models.deletion +from bookwyrm.management.commands.deduplicate_book_data import update_related + + +def convert_review_rating(app_registry, schema_editor): + ''' take reviews with no content and turn them into ratings ''' + db_alias = schema_editor.connection.alias + reviews = app_registry.get_model('bookwyrm', 'Review') + review_ratings = app_registry.get_model('bookwyrm', 'ReviewRating') + ratings = reviews.objects.using(db_alias).filter( + Q(content__isnull=True) | Q(content='')) + # replace the old review with the rating + for review in ratings: + rating = review_ratings.objects.create( + user=review.user, rating=review.rating, book=review.book) + for field in review._meta.get_fields(): + if isinstance(field, ManyToOneRel) or field.name == 'status_ptr': + continue + value = getattr(review, field.name) + print(review, rating, field.name, value) + try: + setattr(rating, field.name, value) + except TypeError: + getattr(rating, field.name).set(value.all()) + rating.save() + update_related(rating, review) + review.delete() + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0029_auto_20201221_2014'), + ] + + operations = [ + migrations.CreateModel( + name='ReviewRating', + fields=[ + ('review_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bookwyrm.Review')), + ], + options={ + 'abstract': False, + }, + bases=('bookwyrm.review',), + ), + migrations.RunPython(convert_review_rating), + ] diff --git a/bookwyrm/models/__init__.py b/bookwyrm/models/__init__.py index 48852cfe4..4a0db4f55 100644 --- a/bookwyrm/models/__init__.py +++ b/bookwyrm/models/__init__.py @@ -8,7 +8,8 @@ from .connector import Connector from .shelf import Shelf, ShelfBook -from .status import Status, GeneratedNote, Review, Comment, Quotation +from .status import Status, GeneratedNote, Comment, Quotation +from .status import Review, ReviewRating from .status import Boost from .attachment import Image from .favorite import Favorite diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 10cee7525..ee8faf005 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -222,6 +222,22 @@ class Review(Status): pure_type = 'Article' +class ReviewRating(Review): + ''' a subtype of review that only contains a rating ''' + def save(self, *args, **kwargs): + if not self.rating: + raise ValueError('Rating object must include a numerical rating') + return super().save(*args, **kwargs) + + @property + def pure_content(self): + #pylint: disable=bad-string-format-type + return 'Rated "%s": %d' % (self.book.title, self.rating) + + activity_serializer = activitypub.Rating + pure_type = 'Note' + + class Boost(Status): ''' boost'ing a post ''' boosted_status = fields.ForeignKey( From dad202823aa73bbfeea9744a518832ff4a7ee6cc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 1 Jan 2021 15:36:43 -0800 Subject: [PATCH 02/14] Moves review re-structing into separate migration --- bookwyrm/migrations/0030_reviewrating.py | 29 --------- .../migrations/0031_auto_20210101_2109.py | 61 +++++++++++++++++++ 2 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 bookwyrm/migrations/0031_auto_20210101_2109.py diff --git a/bookwyrm/migrations/0030_reviewrating.py b/bookwyrm/migrations/0030_reviewrating.py index 3658a666e..327c6c6a8 100644 --- a/bookwyrm/migrations/0030_reviewrating.py +++ b/bookwyrm/migrations/0030_reviewrating.py @@ -1,35 +1,7 @@ # Generated by Django 3.0.7 on 2021-01-01 19:05 -from django.db.models.fields.reverse_related import ManyToOneRel -from django.db.models import Q from django.db import migrations, models import django.db.models.deletion -from bookwyrm.management.commands.deduplicate_book_data import update_related - - -def convert_review_rating(app_registry, schema_editor): - ''' take reviews with no content and turn them into ratings ''' - db_alias = schema_editor.connection.alias - reviews = app_registry.get_model('bookwyrm', 'Review') - review_ratings = app_registry.get_model('bookwyrm', 'ReviewRating') - ratings = reviews.objects.using(db_alias).filter( - Q(content__isnull=True) | Q(content='')) - # replace the old review with the rating - for review in ratings: - rating = review_ratings.objects.create( - user=review.user, rating=review.rating, book=review.book) - for field in review._meta.get_fields(): - if isinstance(field, ManyToOneRel) or field.name == 'status_ptr': - continue - value = getattr(review, field.name) - print(review, rating, field.name, value) - try: - setattr(rating, field.name, value) - except TypeError: - getattr(rating, field.name).set(value.all()) - rating.save() - update_related(rating, review) - review.delete() class Migration(migrations.Migration): @@ -48,5 +20,4 @@ class Migration(migrations.Migration): }, bases=('bookwyrm.review',), ), - migrations.RunPython(convert_review_rating), ] diff --git a/bookwyrm/migrations/0031_auto_20210101_2109.py b/bookwyrm/migrations/0031_auto_20210101_2109.py new file mode 100644 index 000000000..8343719f7 --- /dev/null +++ b/bookwyrm/migrations/0031_auto_20210101_2109.py @@ -0,0 +1,61 @@ +# Generated by Django 3.0.7 on 2021-01-01 21:09 + +from django.db.models.fields.reverse_related import ManyToOneRel +from django.db.models import Q +from django.db import migrations + +def convert_review_rating(app_registry, schema_editor): + ''' take reviews with no content and turn them into ratings ''' + db_alias = schema_editor.connection.alias + reviews = app_registry.get_model('bookwyrm', 'Review') + review_ratings = app_registry.get_model('bookwyrm', 'ReviewRating') + ratings = reviews.objects.using(db_alias).filter( + Q(content__isnull=True) | Q(content='')) + # replace the old review with the rating + for review in ratings: + rating = review_ratings.objects.create( + user=review.user, rating=review.rating, book=review.book) + print('-----') + print(rating, review) + for field in review._meta.get_fields(): + if isinstance(field, ManyToOneRel) or field.name in ['status_ptr', 'id', 'remote_id']: + continue + value = getattr(review, field.name) + try: + setattr(rating, field.name, value) + except TypeError: + getattr(rating, field.name).set(value.all()) + rating.save() + + # move related models away from old review + related_models = [ + (r.remote_field.name, r.related_model.__name__) for r in \ + review._meta.related_objects] + for (related_field, related_model_name) in related_models: + related_model = app_registry.get_model('bookwyrm', related_model_name) + related_objs = related_model.objects.using(db_alias).filter( + **{related_field: review}) + for related_obj in related_objs: + print('related_obj', related_obj) + print('field', related_field) + try: + print(rating) + print('before', getattr(related_obj, related_field)) + setattr(related_obj, related_field, rating) + related_obj.save() + print('after', getattr(related_obj, related_field)) + except TypeError: + getattr(related_obj, related_field).add(rating) + getattr(related_obj, related_field).remove(review) + review.delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0030_reviewrating'), + ] + + operations = [ + migrations.RunPython(convert_review_rating), + ] From ff9caf3d5118c7f575287af9121fe236a67a7027 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 4 Jan 2021 21:37:09 -0800 Subject: [PATCH 03/14] Fixes migration version numbering --- bookwyrm/migrations/0030_reviewrating.py | 23 ------------------- ...to_20210101_2109.py => 0033_reviewrate.py} | 17 +++++++++++--- 2 files changed, 14 insertions(+), 26 deletions(-) delete mode 100644 bookwyrm/migrations/0030_reviewrating.py rename bookwyrm/migrations/{0031_auto_20210101_2109.py => 0033_reviewrate.py} (80%) diff --git a/bookwyrm/migrations/0030_reviewrating.py b/bookwyrm/migrations/0030_reviewrating.py deleted file mode 100644 index 327c6c6a8..000000000 --- a/bookwyrm/migrations/0030_reviewrating.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.0.7 on 2021-01-01 19:05 - -from django.db import migrations, models -import django.db.models.deletion - -class Migration(migrations.Migration): - - dependencies = [ - ('bookwyrm', '0029_auto_20201221_2014'), - ] - - operations = [ - migrations.CreateModel( - name='ReviewRating', - fields=[ - ('review_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bookwyrm.Review')), - ], - options={ - 'abstract': False, - }, - bases=('bookwyrm.review',), - ), - ] diff --git a/bookwyrm/migrations/0031_auto_20210101_2109.py b/bookwyrm/migrations/0033_reviewrate.py similarity index 80% rename from bookwyrm/migrations/0031_auto_20210101_2109.py rename to bookwyrm/migrations/0033_reviewrate.py index 8343719f7..69c0ec578 100644 --- a/bookwyrm/migrations/0031_auto_20210101_2109.py +++ b/bookwyrm/migrations/0033_reviewrate.py @@ -1,8 +1,9 @@ -# Generated by Django 3.0.7 on 2021-01-01 21:09 +# Generated by Django 3.0.7 on 2021-01-05 05:32 from django.db.models.fields.reverse_related import ManyToOneRel from django.db.models import Q -from django.db import migrations +from django.db import migrations, models +import django.db.models.deletion def convert_review_rating(app_registry, schema_editor): ''' take reviews with no content and turn them into ratings ''' @@ -53,9 +54,19 @@ def convert_review_rating(app_registry, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0030_reviewrating'), + ('bookwyrm', '0032_auto_20210104_2055'), ] operations = [ + migrations.CreateModel( + name='ReviewRating', + fields=[ + ('review_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bookwyrm.Review')), + ], + options={ + 'abstract': False, + }, + bases=('bookwyrm.review',), + ), migrations.RunPython(convert_review_rating), ] From 6d7e063b81874c9a797afb5571c3224d4a79ad17 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 25 Feb 2021 10:17:24 -0800 Subject: [PATCH 04/14] Makes rating field mandatory on ratings --- bookwyrm/activitypub/note.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bookwyrm/activitypub/note.py b/bookwyrm/activitypub/note.py index ddb3f7ab9..ad08e3241 100644 --- a/bookwyrm/activitypub/note.py +++ b/bookwyrm/activitypub/note.py @@ -67,7 +67,7 @@ class Review(Comment): @dataclass(init=False) class Rating(Comment): - ''' a full book review ''' - rating: int = None + ''' just a star rating ''' + rating: int content: str = None type: str = 'Rating' From ffd57dfef48e6dd92ab3c43abd5bac51ce8dc2d7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 25 Feb 2021 10:26:24 -0800 Subject: [PATCH 05/14] Use modern string formatting syntax in status model --- bookwyrm/models/status.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 16b32891a..62ce5f1c0 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -258,13 +258,12 @@ class Review(Status): def pure_name(self): ''' clarify review names for mastodon serialization ''' if self.rating: - #pylint: disable=bad-string-format-type - return 'Review of "%s" (%d stars): %s' % ( + return 'Review of "{}" ({:d} stars): {}'.format( self.book.title, self.rating, self.name ) - return 'Review of "%s": %s' % ( + return 'Review of "{}": {}'.format( self.book.title, self.name ) @@ -282,13 +281,13 @@ class ReviewRating(Review): ''' a subtype of review that only contains a rating ''' def save(self, *args, **kwargs): if not self.rating: - raise ValueError('Rating object must include a numerical rating') + raise ValueError( + 'ReviewRating object must include a numerical rating') return super().save(*args, **kwargs) @property def pure_content(self): - #pylint: disable=bad-string-format-type - return 'Rated "%s": %d stars' % (self.book.title, self.rating) + return 'Rated "{}": {:d} stars'.format(self.book.title, self.rating) activity_serializer = activitypub.Rating pure_type = 'Note' From 2e36cfbcf64ec62d5ee10253fb8530df63f598f0 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 25 Feb 2021 14:58:09 -0800 Subject: [PATCH 06/14] Creates new semi-functional migration --- bookwyrm/migrations/0033_reviewrate.py | 72 ------------------------ bookwyrm/migrations/0046_reviewrating.py | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 72 deletions(-) delete mode 100644 bookwyrm/migrations/0033_reviewrate.py create mode 100644 bookwyrm/migrations/0046_reviewrating.py diff --git a/bookwyrm/migrations/0033_reviewrate.py b/bookwyrm/migrations/0033_reviewrate.py deleted file mode 100644 index 69c0ec578..000000000 --- a/bookwyrm/migrations/0033_reviewrate.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by Django 3.0.7 on 2021-01-05 05:32 - -from django.db.models.fields.reverse_related import ManyToOneRel -from django.db.models import Q -from django.db import migrations, models -import django.db.models.deletion - -def convert_review_rating(app_registry, schema_editor): - ''' take reviews with no content and turn them into ratings ''' - db_alias = schema_editor.connection.alias - reviews = app_registry.get_model('bookwyrm', 'Review') - review_ratings = app_registry.get_model('bookwyrm', 'ReviewRating') - ratings = reviews.objects.using(db_alias).filter( - Q(content__isnull=True) | Q(content='')) - # replace the old review with the rating - for review in ratings: - rating = review_ratings.objects.create( - user=review.user, rating=review.rating, book=review.book) - print('-----') - print(rating, review) - for field in review._meta.get_fields(): - if isinstance(field, ManyToOneRel) or field.name in ['status_ptr', 'id', 'remote_id']: - continue - value = getattr(review, field.name) - try: - setattr(rating, field.name, value) - except TypeError: - getattr(rating, field.name).set(value.all()) - rating.save() - - # move related models away from old review - related_models = [ - (r.remote_field.name, r.related_model.__name__) for r in \ - review._meta.related_objects] - for (related_field, related_model_name) in related_models: - related_model = app_registry.get_model('bookwyrm', related_model_name) - related_objs = related_model.objects.using(db_alias).filter( - **{related_field: review}) - for related_obj in related_objs: - print('related_obj', related_obj) - print('field', related_field) - try: - print(rating) - print('before', getattr(related_obj, related_field)) - setattr(related_obj, related_field, rating) - related_obj.save() - print('after', getattr(related_obj, related_field)) - except TypeError: - getattr(related_obj, related_field).add(rating) - getattr(related_obj, related_field).remove(review) - review.delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('bookwyrm', '0032_auto_20210104_2055'), - ] - - operations = [ - migrations.CreateModel( - name='ReviewRating', - fields=[ - ('review_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bookwyrm.Review')), - ], - options={ - 'abstract': False, - }, - bases=('bookwyrm.review',), - ), - migrations.RunPython(convert_review_rating), - ] diff --git a/bookwyrm/migrations/0046_reviewrating.py b/bookwyrm/migrations/0046_reviewrating.py new file mode 100644 index 000000000..b29cdbd29 --- /dev/null +++ b/bookwyrm/migrations/0046_reviewrating.py @@ -0,0 +1,59 @@ +# Generated by Django 3.0.7 on 2021-02-25 18:36 + +from django.db import migrations, models +from django.db import connection +from django.db.models import Q +import django.db.models.deletion + +def convert_review_rating(app_registry, schema_editor): + ''' take rating type Reviews and conver them to ReviewRatings ''' + db_alias = schema_editor.connection.alias + + reviews = app_registry.get_model( + 'bookwyrm', 'Review' + ).objects.using(db_alias).filter( + Q(content__isnull=True) | Q(content='') + ) + + with connection.cursor() as cursor: + for review in reviews: + cursor.execute(''' +INSERT INTO bookwyrm_reviewrating(review_ptr_id) +SELECT status_ptr_id FROM bookwyrm_review +WHERE status_ptr_id={:d}'''.format(review.id)) + +def unconvert_review_rating(app_registry, schema_editor): + ''' undo the conversion from ratings back to reviews''' + # TODO: this does not work + db_alias = schema_editor.connection.alias + + ratings = app_registry.get_model( + 'bookwyrm', 'ReviewRating' + ).objects.using(db_alias).all() + + with connection.cursor() as cursor: + for rating in ratings: + cursor.execute(''' +INSERT INTO bookwyrm_review(status_ptr_id) +SELECT review_ptr_id FROM bookwyrm_reviewrating +WHERE review_ptr_id={:d}'''.format(rating.id)) + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0045_auto_20210210_2114'), + ] + + operations = [ + migrations.CreateModel( + name='ReviewRating', + fields=[ + ('review_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bookwyrm.Review')), + ], + options={ + 'abstract': False, + }, + bases=('bookwyrm.review',), + ), + migrations.RunPython(convert_review_rating, unconvert_review_rating), + ] From 4a10c99026475e6dc79ba40d24dd4a98491bc076 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 25 Feb 2021 15:05:51 -0800 Subject: [PATCH 07/14] Fixes handling of ratings in status views and urls --- bookwyrm/templates/snippets/status/status_content.html | 2 +- bookwyrm/templates/snippets/status/status_header.html | 2 +- bookwyrm/urls.py | 1 + bookwyrm/views/status.py | 4 +++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bookwyrm/templates/snippets/status/status_content.html b/bookwyrm/templates/snippets/status/status_content.html index 0f59f7fcb..e493e4bfd 100644 --- a/bookwyrm/templates/snippets/status/status_content.html +++ b/bookwyrm/templates/snippets/status/status_content.html @@ -1,6 +1,6 @@ {% load bookwyrm_tags %}
- {% if status.status_type == 'Review' %} + {% if status.status_type == 'Review' or status.status_type == 'Rating' %}

{% if status.name %}{{ status.name }}
{% endif %} diff --git a/bookwyrm/templates/snippets/status/status_header.html b/bookwyrm/templates/snippets/status/status_header.html index 890b4ab86..f2e897ccb 100644 --- a/bookwyrm/templates/snippets/status/status_header.html +++ b/bookwyrm/templates/snippets/status/status_header.html @@ -4,7 +4,7 @@ {% if status.status_type == 'GeneratedNote' %} {{ status.content | safe }} -{% elif status.status_type == 'Review' and not status.name and not status.content%} +{% elif status.status_type == 'Rating' %} rated {% elif status.status_type == 'Review' %} reviewed diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index a741088a2..76054e3fd 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -13,6 +13,7 @@ local_user_path = r'^user/(?P%s)' % regex.localname status_types = [ 'status', 'review', + 'reviewrating', 'comment', 'quotation', 'boost', diff --git a/bookwyrm/views/status.py b/bookwyrm/views/status.py index db924ce8b..983fea382 100644 --- a/bookwyrm/views/status.py +++ b/bookwyrm/views/status.py @@ -56,7 +56,7 @@ class CreateStatus(View): status.mention_users.set(set(status.mention_users.all())) # don't apply formatting to generated notes - if not isinstance(status, models.GeneratedNote): + if not isinstance(status, models.GeneratedNote) and content: status.content = to_markdown(content) # do apply formatting to quotes if hasattr(status, 'quote'): @@ -82,6 +82,8 @@ class DeleteStatus(View): def find_mentions(content): ''' detect @mentions in raw status content ''' + if not content: + return for match in re.finditer(regex.strict_username, content): username = match.group().strip().split('@')[1:] if len(username) == 1: From 3ba6479e79ad5280273aa57aca6c9a6535099de4 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Thu, 25 Feb 2021 15:16:16 -0800 Subject: [PATCH 08/14] hide linter error on override funtion --- bookwyrm/activitypub/note.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/activitypub/note.py b/bookwyrm/activitypub/note.py index 54c69ce44..452184217 100644 --- a/bookwyrm/activitypub/note.py +++ b/bookwyrm/activitypub/note.py @@ -11,7 +11,7 @@ class Tombstone(ActivityObject): ''' the placeholder for a deleted status ''' type: str = 'Tombstone' - def to_model(self, *args, **kwargs): + def to_model(self, *args, **kwargs):# pylint: disable=unused-argument ''' this should never really get serialized, just searched for ''' model = apps.get_model('bookwyrm.Status') return model.find_existing_by_remote_id(self.id) From ee7388052c45f521cdff5d00c63ab6b07d43b2c1 Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Fri, 26 Feb 2021 22:57:26 -0800 Subject: [PATCH 09/14] Use SQL parameters, and make unconvert work DBAs don't want you to know about this One Simple Trick --- bookwyrm/migrations/0046_reviewrating.py | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/bookwyrm/migrations/0046_reviewrating.py b/bookwyrm/migrations/0046_reviewrating.py index b29cdbd29..776cae841 100644 --- a/bookwyrm/migrations/0046_reviewrating.py +++ b/bookwyrm/migrations/0046_reviewrating.py @@ -6,7 +6,7 @@ from django.db.models import Q import django.db.models.deletion def convert_review_rating(app_registry, schema_editor): - ''' take rating type Reviews and conver them to ReviewRatings ''' + ''' take rating type Reviews and convert them to ReviewRatings ''' db_alias = schema_editor.connection.alias reviews = app_registry.get_model( @@ -20,23 +20,13 @@ def convert_review_rating(app_registry, schema_editor): cursor.execute(''' INSERT INTO bookwyrm_reviewrating(review_ptr_id) SELECT status_ptr_id FROM bookwyrm_review -WHERE status_ptr_id={:d}'''.format(review.id)) +WHERE status_ptr_id=%s''', (review.id)) def unconvert_review_rating(app_registry, schema_editor): ''' undo the conversion from ratings back to reviews''' - # TODO: this does not work - db_alias = schema_editor.connection.alias - - ratings = app_registry.get_model( - 'bookwyrm', 'ReviewRating' - ).objects.using(db_alias).all() - - with connection.cursor() as cursor: - for rating in ratings: - cursor.execute(''' -INSERT INTO bookwyrm_review(status_ptr_id) -SELECT review_ptr_id FROM bookwyrm_reviewrating -WHERE review_ptr_id={:d}'''.format(rating.id)) + # All we need to do to revert this is drop the table, which Django will do + # on its own, as long as we have a valid reverse function. So, this is a + # no-op function so Django will do its thing class Migration(migrations.Migration): From 717cbe303412e40feb4cf3553ed0cc760eec581c Mon Sep 17 00:00:00 2001 From: Joel Bradshaw Date: Fri, 26 Feb 2021 23:12:39 -0800 Subject: [PATCH 10/14] Use very fancy SQL nonsense This should be more efficient than running the queries one by one --- bookwyrm/migrations/0046_reviewrating.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bookwyrm/migrations/0046_reviewrating.py b/bookwyrm/migrations/0046_reviewrating.py index 776cae841..e410ba91f 100644 --- a/bookwyrm/migrations/0046_reviewrating.py +++ b/bookwyrm/migrations/0046_reviewrating.py @@ -4,6 +4,7 @@ from django.db import migrations, models from django.db import connection from django.db.models import Q import django.db.models.deletion +from psycopg2.extras import execute_values def convert_review_rating(app_registry, schema_editor): ''' take rating type Reviews and convert them to ReviewRatings ''' @@ -16,11 +17,10 @@ def convert_review_rating(app_registry, schema_editor): ) with connection.cursor() as cursor: - for review in reviews: - cursor.execute(''' + values = [(r.id,) for r in reviews] + execute_values(cursor, ''' INSERT INTO bookwyrm_reviewrating(review_ptr_id) -SELECT status_ptr_id FROM bookwyrm_review -WHERE status_ptr_id=%s''', (review.id)) +VALUES %s''', values) def unconvert_review_rating(app_registry, schema_editor): ''' undo the conversion from ratings back to reviews''' From 0cf2baccac45c92e7c4cb706f9b452575961e2d7 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 28 Feb 2021 10:40:10 -0800 Subject: [PATCH 11/14] Adds merge migration --- bookwyrm/migrations/0047_merge_20210228_1839.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 bookwyrm/migrations/0047_merge_20210228_1839.py diff --git a/bookwyrm/migrations/0047_merge_20210228_1839.py b/bookwyrm/migrations/0047_merge_20210228_1839.py new file mode 100644 index 000000000..7e410761a --- /dev/null +++ b/bookwyrm/migrations/0047_merge_20210228_1839.py @@ -0,0 +1,14 @@ +# Generated by Django 3.0.7 on 2021-02-28 18:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0046_reviewrating'), + ('bookwyrm', '0046_sitesettings_privacy_policy'), + ] + + operations = [ + ] From 3bdfc341e410560fc6b2b68504a65f12ce851403 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 8 Mar 2021 09:54:02 -0800 Subject: [PATCH 12/14] Runs black --- bookwyrm/activitypub/note.py | 6 +-- bookwyrm/migrations/0046_reviewrating.py | 43 +++++++++++++------ .../migrations/0047_merge_20210228_1839.py | 7 ++- bookwyrm/models/status.py | 8 ++-- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/bookwyrm/activitypub/note.py b/bookwyrm/activitypub/note.py index bea275d16..a739eafa1 100644 --- a/bookwyrm/activitypub/note.py +++ b/bookwyrm/activitypub/note.py @@ -13,9 +13,9 @@ class Tombstone(ActivityObject): type: str = "Tombstone" - def to_model(self, *args, **kwargs):# pylint: disable=unused-argument - ''' this should never really get serialized, just searched for ''' - model = apps.get_model('bookwyrm.Status') + def to_model(self, *args, **kwargs): # pylint: disable=unused-argument + """ this should never really get serialized, just searched for """ + model = apps.get_model("bookwyrm.Status") return model.find_existing_by_remote_id(self.id) diff --git a/bookwyrm/migrations/0046_reviewrating.py b/bookwyrm/migrations/0046_reviewrating.py index e410ba91f..8d1490042 100644 --- a/bookwyrm/migrations/0046_reviewrating.py +++ b/bookwyrm/migrations/0046_reviewrating.py @@ -6,44 +6,61 @@ from django.db.models import Q import django.db.models.deletion from psycopg2.extras import execute_values + def convert_review_rating(app_registry, schema_editor): - ''' take rating type Reviews and convert them to ReviewRatings ''' + """ take rating type Reviews and convert them to ReviewRatings """ db_alias = schema_editor.connection.alias - reviews = app_registry.get_model( - 'bookwyrm', 'Review' - ).objects.using(db_alias).filter( - Q(content__isnull=True) | Q(content='') + reviews = ( + app_registry.get_model("bookwyrm", "Review") + .objects.using(db_alias) + .filter(Q(content__isnull=True) | Q(content="")) ) with connection.cursor() as cursor: values = [(r.id,) for r in reviews] - execute_values(cursor, ''' + execute_values( + cursor, + """ INSERT INTO bookwyrm_reviewrating(review_ptr_id) -VALUES %s''', values) +VALUES %s""", + values, + ) + def unconvert_review_rating(app_registry, schema_editor): - ''' undo the conversion from ratings back to reviews''' + """ undo the conversion from ratings back to reviews""" # All we need to do to revert this is drop the table, which Django will do # on its own, as long as we have a valid reverse function. So, this is a # no-op function so Django will do its thing + class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0045_auto_20210210_2114'), + ("bookwyrm", "0045_auto_20210210_2114"), ] operations = [ migrations.CreateModel( - name='ReviewRating', + name="ReviewRating", fields=[ - ('review_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='bookwyrm.Review')), + ( + "review_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="bookwyrm.Review", + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, - bases=('bookwyrm.review',), + bases=("bookwyrm.review",), ), migrations.RunPython(convert_review_rating, unconvert_review_rating), ] diff --git a/bookwyrm/migrations/0047_merge_20210228_1839.py b/bookwyrm/migrations/0047_merge_20210228_1839.py index 7e410761a..4be39e56f 100644 --- a/bookwyrm/migrations/0047_merge_20210228_1839.py +++ b/bookwyrm/migrations/0047_merge_20210228_1839.py @@ -6,9 +6,8 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0046_reviewrating'), - ('bookwyrm', '0046_sitesettings_privacy_policy'), + ("bookwyrm", "0046_reviewrating"), + ("bookwyrm", "0046_sitesettings_privacy_policy"), ] - operations = [ - ] + operations = [] diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index 9378772c6..80f2b593a 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -295,11 +295,11 @@ class Review(Status): class ReviewRating(Review): - ''' a subtype of review that only contains a rating ''' + """ a subtype of review that only contains a rating """ + def save(self, *args, **kwargs): if not self.rating: - raise ValueError( - 'ReviewRating object must include a numerical rating') + raise ValueError("ReviewRating object must include a numerical rating") return super().save(*args, **kwargs) @property @@ -307,7 +307,7 @@ class ReviewRating(Review): return 'Rated "{}": {:d} stars'.format(self.book.title, self.rating) activity_serializer = activitypub.Rating - pure_type = 'Note' + pure_type = "Note" class Boost(ActivityMixin, Status): From 84534a299164f3acc2c819100e77484c833d535c Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 8 Mar 2021 09:54:53 -0800 Subject: [PATCH 13/14] Adds merge migration --- bookwyrm/migrations/0048_merge_20210308_1754.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 bookwyrm/migrations/0048_merge_20210308_1754.py diff --git a/bookwyrm/migrations/0048_merge_20210308_1754.py b/bookwyrm/migrations/0048_merge_20210308_1754.py new file mode 100644 index 000000000..6c4488a4f --- /dev/null +++ b/bookwyrm/migrations/0048_merge_20210308_1754.py @@ -0,0 +1,14 @@ +# Generated by Django 3.0.7 on 2021-03-08 17:54 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('bookwyrm', '0047_connector_isbn_search_url'), + ('bookwyrm', '0047_merge_20210228_1839'), + ] + + operations = [ + ] From 5fe989e20f39f9edd4a3b3f7dee7de810c6d6d96 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 8 Mar 2021 09:58:07 -0800 Subject: [PATCH 14/14] Formats migrationwq --- bookwyrm/migrations/0048_merge_20210308_1754.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bookwyrm/migrations/0048_merge_20210308_1754.py b/bookwyrm/migrations/0048_merge_20210308_1754.py index 6c4488a4f..47fa9e771 100644 --- a/bookwyrm/migrations/0048_merge_20210308_1754.py +++ b/bookwyrm/migrations/0048_merge_20210308_1754.py @@ -6,9 +6,8 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('bookwyrm', '0047_connector_isbn_search_url'), - ('bookwyrm', '0047_merge_20210228_1839'), + ("bookwyrm", "0047_connector_isbn_search_url"), + ("bookwyrm", "0047_merge_20210228_1839"), ] - operations = [ - ] + operations = []