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 %}
-
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)