fix potential missing match when link ExternalResource to Item

This commit is contained in:
Your Name 2023-06-28 23:25:36 -04:00 committed by Henri Dickson
parent 771ebbd7ad
commit 86289bdaab
4 changed files with 38 additions and 8 deletions

View file

@ -342,16 +342,16 @@ class Item(SoftDeleteMixin, PolymorphicModel):
)
def merge_to(self, to_item):
self.log_action({"!merged": [str(self.merged_to_item), str(to_item)]})
if to_item is None:
if self.merged_to_item is not None:
self.merged_to_item = None
self.save()
return
elif to_item.merged_to_item is not None:
raise ValueError("cannot merge with an item aleady merged")
if to_item.merged_to_item is not None:
raise ValueError("cannot merge to item which is merged to another item")
if to_item.__class__ != self.__class__:
_logger.warn(f"merging item across class from {self} to {to_item}")
raise ValueError(f"cannot merge to item in a different model")
self.log_action({"!merged": [str(self.merged_to_item), str(to_item)]})
self.merged_to_item = to_item
self.save()
for res in self.external_resources.all():
@ -530,6 +530,8 @@ class ExternalResource(models.Model):
return f"{self.pk}:{self.id_type}:{self.id_value or ''} ({self.url})"
def unlink_from_item(self):
if not self.item:
return
self.item.log_action({"!unlink": [str(self), None]})
self.item = None
self.save()

View file

@ -8,7 +8,7 @@ ResourceContent persists as an ExternalResource which may link to an Item
"""
from typing import Callable
import re
from .models import ExternalResource, IdType, Item
from .models import ExternalResource, IdType, IdealIdTypes, Item
from dataclasses import dataclass, field
import logging
import json
@ -122,6 +122,21 @@ class AbstractSite:
matched = model.objects.filter(
primary_lookup_id_type=t, primary_lookup_id_value=v
).first()
if matched is None:
matched = model.objects.filter(
primary_lookup_id_type=resource.id_type,
primary_lookup_id_value=resource.id_value,
).first()
if matched and matched.merged_to_item:
matched = matched.merged_to_item
if (
matched
and matched.primary_lookup_id_type not in IdealIdTypes
and t in IdealIdTypes
):
matched.primary_lookup_id_type = t
matched.primary_lookup_id_value = v
matched.save()
return matched
@classmethod
@ -211,7 +226,7 @@ class AbstractSite:
p.item.save()
self.scrape_additional_data()
if auto_link:
for linked_resource in p.required_resources:
for linked_resource in p.required_resources: # type: ignore
linked_url = linked_resource.get("url")
if linked_url:
linked_site = SiteManager.get_site_by_url(linked_url)
@ -293,7 +308,7 @@ def crawl_related_resources_task(resource_pk):
_logger.warn(f"crawl resource not found {resource_pk}")
return
links = resource.related_resources
for w in links:
for w in links: # type: ignore
try:
item = None
site = None

View file

@ -172,6 +172,7 @@
<input type="url"
name="new_item_url"
placeholder="目标条目URL留空则取消现有合并"
{% if item.is_deleted and not item.merged_to_item %}disabled{% endif %}
value="{{ item.merged_to_item.absolute_url }}">
<br>
<input class="contrast" type="submit" value="{% trans '合并到同类另一条目' %}">
@ -191,7 +192,7 @@
<input class="contrast"
type="submit"
{% if item.is_deleted or item.merged_to_item %}disabled{% endif %}
value="{% trans '<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>除' %}">
value="{% trans '除' %}">
</form>
</details>
{% endif %}

View file

@ -128,6 +128,18 @@ def delete(request, item_path, item_uuid):
)
@login_required
def undelete(request, item_path, item_uuid):
if request.method != "POST":
raise BadRequest()
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
if not request.user.is_staff:
raise PermissionDenied()
item.is_deleted = False
item.save()
return redirect(item.url)
@login_required
def recast(request, item_path, item_uuid):
if request.method != "POST":