diff --git a/bookwyrm/forms.py b/bookwyrm/forms.py index 1f1f1a3b5..df68334e0 100644 --- a/bookwyrm/forms.py +++ b/bookwyrm/forms.py @@ -156,14 +156,6 @@ class UserGroupForm(CustomForm): fields = ["groups"] -class TagForm(CustomForm): - class Meta: - model = models.Tag - fields = ["name"] - help_texts = {f: None for f in fields} - labels = {"name": "Add a tag"} - - class CoverForm(CustomForm): class Meta: model = models.Book diff --git a/bookwyrm/migrations/0070_auto_20210423_0121.py b/bookwyrm/migrations/0070_auto_20210423_0121.py new file mode 100644 index 000000000..0b04c3ca2 --- /dev/null +++ b/bookwyrm/migrations/0070_auto_20210423_0121.py @@ -0,0 +1,35 @@ +# Generated by Django 3.1.8 on 2021-04-23 01:21 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0069_auto_20210422_1604"), + ] + + operations = [ + migrations.AlterUniqueTogether( + name="usertag", + unique_together=None, + ), + migrations.RemoveField( + model_name="usertag", + name="book", + ), + migrations.RemoveField( + model_name="usertag", + name="tag", + ), + migrations.RemoveField( + model_name="usertag", + name="user", + ), + migrations.DeleteModel( + name="Tag", + ), + migrations.DeleteModel( + name="UserTag", + ), + ] diff --git a/bookwyrm/models/__init__.py b/bookwyrm/models/__init__.py index 35e32c2cf..2a25a5251 100644 --- a/bookwyrm/models/__init__.py +++ b/bookwyrm/models/__init__.py @@ -17,8 +17,6 @@ from .favorite import Favorite from .notification import Notification from .readthrough import ReadThrough, ProgressUpdate, ProgressMode -from .tag import Tag, UserTag - from .user import User, KeyPair, AnnualGoal from .relationship import UserFollows, UserFollowRequest, UserBlocks from .report import Report, ReportComment diff --git a/bookwyrm/models/tag.py b/bookwyrm/models/tag.py deleted file mode 100644 index 2c45b8f91..000000000 --- a/bookwyrm/models/tag.py +++ /dev/null @@ -1,63 +0,0 @@ -""" models for storing different kinds of Activities """ -import urllib.parse - -from django.apps import apps -from django.db import models - -from bookwyrm import activitypub -from bookwyrm.settings import DOMAIN -from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin -from .base_model import BookWyrmModel -from . import fields - - -class Tag(OrderedCollectionMixin, BookWyrmModel): - """ freeform tags for books """ - - name = fields.CharField(max_length=100, unique=True) - identifier = models.CharField(max_length=100) - - @property - def books(self): - """ count of books associated with this tag """ - edition_model = apps.get_model("bookwyrm.Edition", require_ready=True) - return ( - edition_model.objects.filter(usertag__tag__identifier=self.identifier) - .order_by("-created_date") - .distinct() - ) - - collection_queryset = books - - def get_remote_id(self): - """ tag should use identifier not id in remote_id """ - base_path = "https://%s" % DOMAIN - return "%s/tag/%s" % (base_path, self.identifier) - - def save(self, *args, **kwargs): - """ create a url-safe lookup key for the tag """ - if not self.id: - # add identifiers to new tags - self.identifier = urllib.parse.quote_plus(self.name) - super().save(*args, **kwargs) - - -class UserTag(CollectionItemMixin, BookWyrmModel): - """ an instance of a tag on a book by a user """ - - user = fields.ForeignKey( - "User", on_delete=models.PROTECT, activitypub_field="actor" - ) - book = fields.ForeignKey( - "Edition", on_delete=models.PROTECT, activitypub_field="object" - ) - tag = fields.ForeignKey("Tag", on_delete=models.PROTECT, activitypub_field="target") - - activity_serializer = activitypub.Add - object_field = "book" - collection_field = "tag" - - class Meta: - """ unqiueness constraint """ - - unique_together = ("user", "book", "tag") diff --git a/bookwyrm/templates/snippets/tag.html b/bookwyrm/templates/snippets/tag.html deleted file mode 100644 index 507def723..000000000 --- a/bookwyrm/templates/snippets/tag.html +++ /dev/null @@ -1,23 +0,0 @@ -{% load i18n %} -
-
- {% csrf_token %} - - - -
- - {{ tag.tag.name }} - - {% if tag.tag.identifier in user_tags %} - - {% else %} - - {% endif %} -
-
-
diff --git a/bookwyrm/templates/tag.html b/bookwyrm/templates/tag.html deleted file mode 100644 index b6fa67783..000000000 --- a/bookwyrm/templates/tag.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends 'layout.html' %} -{% load i18n %} -{% load bookwyrm_tags %} - -{% block title %}{{ tag.name }}{% endblock %} - -{% block content %} -
-

{% blocktrans %}Books tagged "{{ tag.name }}"{% endblocktrans %}

- {% include 'snippets/book_tiles.html' with books=books.all %} -
-{% endblock %} - - diff --git a/bookwyrm/tests/views/test_tag.py b/bookwyrm/tests/views/test_tag.py deleted file mode 100644 index 6ad6ab254..000000000 --- a/bookwyrm/tests/views/test_tag.py +++ /dev/null @@ -1,119 +0,0 @@ -""" test for app action functionality """ -from unittest.mock import patch -from django.contrib.auth.models import Group, Permission -from django.contrib.contenttypes.models import ContentType -from django.template.response import TemplateResponse -from django.test import TestCase -from django.test.client import RequestFactory - -from bookwyrm import models, views -from bookwyrm.activitypub import ActivitypubResponse - - -class TagViews(TestCase): - """ tag views""" - - def setUp(self): - """ we need basic test data and mocks """ - self.factory = RequestFactory() - self.local_user = models.User.objects.create_user( - "mouse@local.com", - "mouse@mouse.com", - "mouseword", - local=True, - localname="mouse", - remote_id="https://example.com/users/mouse", - ) - self.group = Group.objects.create(name="editor") - self.group.permissions.add( - Permission.objects.create( - name="edit_book", - codename="edit_book", - content_type=ContentType.objects.get_for_model(models.User), - ).id - ) - self.work = models.Work.objects.create(title="Test Work") - self.book = models.Edition.objects.create( - title="Example Edition", - remote_id="https://example.com/book/1", - parent_work=self.work, - ) - models.SiteSettings.objects.create() - - def test_tag_page(self): - """ there are so many views, this just makes sure it LOADS """ - view = views.Tag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="hi there") - models.UserTag.objects.create(tag=tag, user=self.local_user, book=self.book) - request = self.factory.get("") - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = False - result = view(request, tag.identifier) - self.assertIsInstance(result, TemplateResponse) - result.render() - self.assertEqual(result.status_code, 200) - - request = self.factory.get("") - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = True - result = view(request, tag.identifier) - self.assertIsInstance(result, ActivitypubResponse) - self.assertEqual(result.status_code, 200) - - def test_tag_page_activitypub_page(self): - """ there are so many views, this just makes sure it LOADS """ - view = views.Tag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="hi there") - models.UserTag.objects.create(tag=tag, user=self.local_user, book=self.book) - request = self.factory.get("", {"page": 1}) - with patch("bookwyrm.views.tag.is_api_request") as is_api: - is_api.return_value = True - result = view(request, tag.identifier) - self.assertIsInstance(result, ActivitypubResponse) - self.assertEqual(result.status_code, 200) - - def test_tag(self): - """ add a tag to a book """ - view = views.AddTag.as_view() - request = self.factory.post( - "", - { - "name": "A Tag!?", - "book": self.book.id, - }, - ) - request.user = self.local_user - - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - view(request) - - tag = models.Tag.objects.get() - user_tag = models.UserTag.objects.get() - self.assertEqual(tag.name, "A Tag!?") - self.assertEqual(tag.identifier, "A+Tag%21%3F") - self.assertEqual(user_tag.user, self.local_user) - self.assertEqual(user_tag.book, self.book) - - def test_untag(self): - """ remove a tag from a book """ - view = views.RemoveTag.as_view() - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - tag = models.Tag.objects.create(name="A Tag!?") - models.UserTag.objects.create(user=self.local_user, book=self.book, tag=tag) - request = self.factory.post( - "", - { - "user": self.local_user.id, - "book": self.book.id, - "name": tag.name, - }, - ) - request.user = self.local_user - - with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"): - view(request) - - self.assertTrue(models.Tag.objects.filter(name="A Tag!?").exists()) - self.assertFalse(models.UserTag.objects.exists()) diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 8c5266a6e..3ad064b23 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -277,11 +277,6 @@ urlpatterns = [ # author re_path(r"^author/(?P\d+)(.json)?/?$", views.Author.as_view()), re_path(r"^author/(?P\d+)/edit/?$", views.EditAuthor.as_view()), - # tags - re_path(r"^tag/(?P.+)\.json/?$", views.Tag.as_view()), - re_path(r"^tag/(?P.+)/?$", views.Tag.as_view()), - re_path(r"^tag/?$", views.AddTag.as_view()), - re_path(r"^untag/?$", views.RemoveTag.as_view()), # reading progress re_path(r"^edit-readthrough/?$", views.edit_readthrough, name="edit-readthrough"), re_path(r"^delete-readthrough/?$", views.delete_readthrough), diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index c0f35ba81..bcd914e10 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -34,7 +34,6 @@ from .shelf import create_shelf, delete_shelf from .shelf import shelve, unshelve from .site import Site from .status import CreateStatus, DeleteStatus, DeleteAndRedraft -from .tag import Tag, AddTag, RemoveTag from .updates import get_notification_count, get_unread_status_count from .user import User, EditUser, Followers, Following from .user_admin import UserAdmin, UserAdminList diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index 0c61d1a20..34ebe0b68 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -57,12 +57,7 @@ class Book(View): ) reviews_page = paginated.get_page(request.GET.get("page")) - user_tags = readthroughs = user_shelves = other_edition_shelves = [] if request.user.is_authenticated: - user_tags = models.UserTag.objects.filter( - book=book, user=request.user - ).values_list("tag__identifier", flat=True) - readthroughs = models.ReadThrough.objects.filter( user=request.user, book=book, @@ -87,11 +82,9 @@ class Book(View): "review_count": reviews.count(), "ratings": reviews.filter(Q(content__isnull=True) | Q(content="")), "rating": reviews.aggregate(Avg("rating"))["rating__avg"], - "tags": models.UserTag.objects.filter(book=book), "lists": privacy_filter( request.user, book.list_set.filter(listitem__approved=True) ), - "user_tags": user_tags, "user_shelves": user_shelves, "other_edition_shelves": other_edition_shelves, "readthroughs": readthroughs, diff --git a/bookwyrm/views/tag.py b/bookwyrm/views/tag.py deleted file mode 100644 index a6bdf05a2..000000000 --- a/bookwyrm/views/tag.py +++ /dev/null @@ -1,73 +0,0 @@ -""" tagging views""" -from django.contrib.auth.decorators import login_required -from django.shortcuts import get_object_or_404, redirect -from django.template.response import TemplateResponse -from django.utils.decorators import method_decorator -from django.views import View - -from bookwyrm import models -from bookwyrm.activitypub import ActivitypubResponse -from .helpers import is_api_request - - -# pylint: disable= no-self-use -class Tag(View): - """ tag page """ - - def get(self, request, tag_id): - """ see books related to a tag """ - tag_obj = get_object_or_404(models.Tag, identifier=tag_id) - - if is_api_request(request): - return ActivitypubResponse(tag_obj.to_activity(**request.GET)) - - books = models.Edition.objects.filter( - usertag__tag__identifier=tag_id - ).distinct() - data = { - "books": books, - "tag": tag_obj, - } - return TemplateResponse(request, "tag.html", data) - - -@method_decorator(login_required, name="dispatch") -class AddTag(View): - """ add a tag to a book """ - - def post(self, request): - """ tag a book """ - # I'm not using a form here because sometimes "name" is sent as a hidden - # field which doesn't validate - name = request.POST.get("name") - book_id = request.POST.get("book") - book = get_object_or_404(models.Edition, id=book_id) - tag_obj, _ = models.Tag.objects.get_or_create( - name=name, - ) - models.UserTag.objects.get_or_create( - user=request.user, - book=book, - tag=tag_obj, - ) - - return redirect("/book/%s" % book_id) - - -@method_decorator(login_required, name="dispatch") -class RemoveTag(View): - """ remove a user's tag from a book """ - - def post(self, request): - """ untag a book """ - name = request.POST.get("name") - tag_obj = get_object_or_404(models.Tag, name=name) - book_id = request.POST.get("book") - book = get_object_or_404(models.Edition, id=book_id) - - user_tag = get_object_or_404( - models.UserTag, tag=tag_obj, book=book, user=request.user - ) - user_tag.delete() - - return redirect("/book/%s" % book_id)