diff --git a/catalog/search/views.py b/catalog/search/views.py
index 2e3c7ee8..1e77a59a 100644
--- a/catalog/search/views.py
+++ b/catalog/search/views.py
@@ -175,7 +175,10 @@ def external_search(request):
)
+@login_required
def refetch(request):
+ if request.method != "POST":
+ return HttpResponseBadRequest()
url = request.POST.get("url")
if not url:
return HttpResponseBadRequest()
diff --git a/catalog/templates/album.html b/catalog/templates/album.html
index b3289fc3..9dfcf2f4 100644
--- a/catalog/templates/album.html
+++ b/catalog/templates/album.html
@@ -105,9 +105,6 @@
{% if user.is_authenticated %}
{% trans '编辑' %}{{ item.demonstrative }}
{% endif %}
- {% if user.is_staff %}
- / {% trans '删除' %}
- {% endif %}
{% endblock %}
diff --git a/catalog/templates/catalog_edit.html b/catalog/templates/catalog_edit.html
index 9bfa346c..c43fc57d 100644
--- a/catalog/templates/catalog_edit.html
+++ b/catalog/templates/catalog_edit.html
@@ -23,6 +23,7 @@
+ {% if item %}
{% endfor %}
+
+ {% if request.user.is_staff %}
+
+
+
{% trans '合并到另一条目' %}
+
+
+
+
+
+
+
{% trans '删除' %}
+
+
+
+
+
+ {% if item.is_deteled %}
+
+ {% endif %}
+
+ {% endif %}
+
+ {% endif %}
+
+
diff --git a/catalog/templates/edition.html b/catalog/templates/edition.html
index e1455579..af058098 100644
--- a/catalog/templates/edition.html
+++ b/catalog/templates/edition.html
@@ -41,8 +41,8 @@
{% if item.translator %}{% trans '译者:' %}
{% for translator in item.translator %}
{{ translator }}{% if not forloop.last %} / {% endif %}
- {% endfor %}
- {% endif %}
+ {% endfor %}
+ {% endif %}
{% if item.orig_title %}{% trans '原作名:' %}{{ item.orig_title }}{% endif %}
{% if item.language %}{% trans '语言:' %}{{ item.language }}{% endif %}
{%if item.pub_year %}{% trans '出版时间:' %}{{ item.pub_year }}{% trans '年' %}{% if item.pub_month %}{{ item.pub_month }}{% trans '月' %}{% endif %}{% endif %}
@@ -53,7 +53,7 @@
{% if item.price %}{% trans '定价:' %}{{ item.price }}{% endif %}
{% if item.pages %}{% trans '页数:' %}{{ item.pages }}{% endif %}
{% if item.imprint %}{% trans '出品方:' %}{{ item.imprint }}{% endif %}
- {% if item.other_info %}
+ {% if item.other_info %}
{% for k, v in item.other_info.items %}
{% endblock %}
diff --git a/catalog/templates/item_base.html b/catalog/templates/item_base.html
index dd7724f2..762439e7 100644
--- a/catalog/templates/item_base.html
+++ b/catalog/templates/item_base.html
@@ -45,6 +45,12 @@
+ {% if item.is_deleted %}
+ [DELETED]
+ {% endif %}
+ {% if item.merged_to_item %}
+ [MERGED]
{{ item.merged_to_item.title }}
+ {% endif %}
{% block title %}
{{ item.title }}
@@ -122,7 +128,7 @@
{% trans '全部标记' %}
关注的人的标记
{% endif %}
-
+
{% for others_mark in mark_list %}
-
diff --git a/catalog/templates/movie.html b/catalog/templates/movie.html
index 8409c21e..45635703 100644
--- a/catalog/templates/movie.html
+++ b/catalog/templates/movie.html
@@ -163,9 +163,6 @@
{% if user.is_authenticated %}
{% trans '编辑' %}{{ item.demonstrative }}
{% endif %}
- {% if user.is_staff %}
- / {% trans '删除' %}
- {% endif %}
{% endblock %}
diff --git a/catalog/urls.py b/catalog/urls.py
index b2595f96..f71a4d57 100644
--- a/catalog/urls.py
+++ b/catalog/urls.py
@@ -69,5 +69,6 @@ urlpatterns = [
path("search/external/", external_search, name="external_search"),
path("fetch_refresh/", fetch_refresh, name="fetch_refresh"),
path("refetch", refetch, name="refetch"),
+ path("unlink", unlink, name="unlink"),
path("api/", api.urls),
]
diff --git a/catalog/views.py b/catalog/views.py
index e1bc3e24..63afe1a1 100644
--- a/catalog/views.py
+++ b/catalog/views.py
@@ -17,6 +17,7 @@ from django.db.models import Count
from django.utils import timezone
from django.core.paginator import Paginator
from polymorphic.base import django
+from catalog.common.models import ExternalResource
from catalog.common.sites import AbstractSite, SiteManager
from mastodon import mastodon_request_included
from mastodon.models import MastodonApplication
@@ -58,6 +59,11 @@ def retrieve(request, item_path, item_uuid):
item_url = f"/{item_path}/{item_uuid}"
if item.url != item_url:
return redirect(item.url)
+ skipcheck = request.GET.get("skipcheck", False) and request.user.is_staff
+ if not skipcheck and item.merged_to_item:
+ return redirect(item.merged_to_item.url)
+ if not skipcheck and item.is_deleted:
+ return HttpResponseNotFound("item not found")
mark = None
review = None
mark_list = None
@@ -148,7 +154,7 @@ def edit(request, item_path, item_uuid):
"catalog_edit.html",
{
"form": form,
- "is_update": True,
+ "item": item,
},
)
elif request.method == "POST":
@@ -176,7 +182,29 @@ def delete(request, item_path, item_uuid):
return HttpResponseBadRequest()
if not request.user.is_staff:
raise PermissionDenied()
- return HttpResponseBadRequest()
+ item = get_object_or_404(Item, uid=base62.decode(item_uuid))
+ for res in item.external_resources.all():
+ res.item = None
+ res.save()
+ item.delete()
+ return (
+ redirect(item.url + "?skipcheck=1") if request.user.is_staff else redirect("/")
+ )
+
+
+@login_required
+def unlink(request):
+ if request.method != "POST":
+ return HttpResponseBadRequest()
+ if not request.user.is_staff:
+ raise PermissionDenied()
+ res_id = request.POST.get("id")
+ if not res_id:
+ return HttpResponseBadRequest()
+ resource = get_object_or_404(ExternalResource, id=res_id)
+ resource.item = None
+ resource.save()
+ return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
@login_required
@@ -189,6 +217,7 @@ def merge(request, item_path, item_uuid):
new_item = Item.get_by_url(request.POST.get("new_item_url"))
if not new_item or new_item.is_deleted or new_item.merged_to_item_id:
return HttpResponseBadRequest(b"invalid new item")
+ _logger.warn(f"{request.user} merges {item} to {new_item}")
item.merge_to(new_item)
update_journal_for_merged_item(item_uuid)
return redirect(new_item.url)
diff --git a/journal/migrations/0008_alter_shelfmember_unique_together.py b/journal/migrations/0008_alter_shelfmember_unique_together.py
new file mode 100644
index 00000000..285084e8
--- /dev/null
+++ b/journal/migrations/0008_alter_shelfmember_unique_together.py
@@ -0,0 +1,20 @@
+# Generated by Django 3.2.16 on 2023-01-23 05:05
+
+from django.conf import settings
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("catalog", "0002_initial"),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ("journal", "0007_alter_collection_catalog_item"),
+ ]
+
+ operations = [
+ migrations.AlterUniqueTogether(
+ name="shelfmember",
+ unique_together={("owner", "item")},
+ ),
+ ]
diff --git a/journal/models.py b/journal/models.py
index bcdc6b99..3733f0d4 100644
--- a/journal/models.py
+++ b/journal/models.py
@@ -96,7 +96,7 @@ def query_item_category(item_category):
class Piece(PolymorphicModel, UserOwnedObjectMixin):
- url_path = "piece" # subclass must specify this
+ url_path = "p" # subclass must specify this
uid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True)
@property
@@ -494,7 +494,7 @@ class ShelfMember(ListMember):
)
class Meta:
- unique_together = [["parent", "item"]]
+ unique_together = [["owner", "item"]]
@cached_property
def mark(self):
@@ -1054,12 +1054,13 @@ def update_journal_for_merged_item(legacy_item_uuid):
_logger.error("update_journal_for_merged_item: unable to find item")
return
new_item = legacy_item.merged_to_item
- for cls in Content.__subclasses__ + ListMember.__subclasses__:
- _logger.info(f"update {cls.__name__}: {legacy_item} -> {new_item}")
+ for cls in list(Content.__subclasses__()) + list(ListMember.__subclasses__()):
for p in cls.objects.filter(item=legacy_item):
try:
p.item = new_item
p.save(update_fields=["item_id"])
except:
- _logger.info(f"delete duplicated piece {p}")
+ _logger.warn(
+ f"deleted piece {p} when merging {cls.__name__}: {legacy_item} -> {new_item}"
+ )
p.delete()