This commit is contained in:
Your Name 2023-01-23 21:24:31 -05:00 committed by Henri Dickson
parent 2da1991025
commit d2bfbb727f
9 changed files with 77 additions and 24 deletions

View file

@ -14,6 +14,7 @@ from .utils import DEFAULT_ITEM_COVER, item_cover_path, resource_cover_path
from .mixins import SoftDeleteMixin
from django.conf import settings
from users.models import User
from django.db import connection
_logger = logging.getLogger(__name__)
@ -264,10 +265,20 @@ class Item(SoftDeleteMixin, PolymorphicModel):
res.item = to_item
res.save()
def switch_class_to(self, cls):
_logger.warn(f"switch item across class from {self} to {cls}")
# TODO
pass
def recast_to(self, model):
_logger.warn(f"recast item {self} to {model}")
if self.__class__ == model:
return self
if model not in Item.__subclasses__():
raise ValueError("invalid model to recast to")
ct = ContentType.objects.get_for_model(model)
tbl = self.__class__._meta.db_table
obj = model(item_ptr_id=self.pk, polymorphic_ctype=ct)
obj.save_base(raw=True)
obj.save(update_fields=["polymorphic_ctype"])
with connection.cursor() as cursor:
cursor.execute(f"DELETE FROM {tbl} WHERE item_ptr_id = %s", [self.pk])
return model.objects.get(pk=obj.pk)
@property
def uuid(self):

View file

@ -170,7 +170,9 @@ class Indexer:
for field in obj.__class__.indexable_fields:
item[field] = getattr(obj, field)
for field in obj.__class__.indexable_fields_time:
item[field] = getattr(obj, field).timestamp()
item[field] = (
getattr(obj, field).timestamp() if getattr(obj, field) else None
)
for field in obj.__class__.indexable_fields_float:
item[field] = float(getattr(obj, field)) if getattr(obj, field) else None
for field in obj.__class__.indexable_fields_dict:

View file

@ -52,17 +52,33 @@
{% if request.user.is_staff %}
<div class="aside-section-wrapper">
<div class="action-panel">
{% if item.class_name == "movie" or item.class_name == "tvshow" %}
<div class="action-panel__label">{% trans '切换分类' %} </div>
<div class="action-panel__button-group">
<form method="post" action="{% url 'catalog:recast' item.url_path item.uuid %}" onsubmit="return confirm('Confirm updating?');">
{% csrf_token %}
{% if item.class_name == "movie" %}
<input type="hidden" value="tvshow" name="class">
<input class="button" type="submit" value="{% trans '更改为剧集' %}">
{% endif %}
{% if item.class_name == "tvshow" %}
<input type="hidden" value="movie" name="class">
<input class="button" type="submit" value="{% trans '更改为电影' %}">
{% endif %}
</form>
</div>
{% endif %}
<div class="action-panel__label">{% trans '合并到另一条目' %} </div>
<div class="action-panel__button-group">
<form method="post" action="{% url 'catalog:merge' item.url_path item.uuid %}" onsubmit="return confirm('Confirm merging?');">
{% csrf_token %}
<input type="url" name="new_item_url" placeholder="目标条目URL" value="{{ item.merged_to_item.url }}" required><br>
<input type="url" name="new_item_url" placeholder="目标条目URL" value="{{ item.merged_to_item.absolute_url }}" required><br>
<input class="button" type="submit" value="{% trans '提交' %}">
</form>
</div>
</div>
<div class="action-panel">
<div class="action-panel__label">{% trans '删除' %} </div>
<div class="action-panel__button-group">
<form method="post" action="{% url 'catalog:delete' item.url_path item.uuid %}" onsubmit="return confirm('Confirm deletion?');">

View file

@ -99,9 +99,6 @@
{% if user.is_authenticated %}
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
{% endif %}
{% if user.is_staff %}
/<a href="{% url 'catalog:delete' item.url_path item.uuid %}"> {% trans '删除' %}</a>
{% endif %}
</div>
</div>
{% endblock %}

View file

@ -177,9 +177,6 @@
{% if user.is_authenticated %}
<a href="{% url 'catalog:edit' item.url_path item.uuid %}">{% trans '编辑' %}{{ item.demonstrative }}</a>
{% endif %}
{% if user.is_staff %}
/<a href="{% url 'catalog:delete' item.url_path item.uuid %}"> {% trans '删除' %}</a>
{% endif %}
</div>
</div>
{% endblock %}

View file

@ -134,3 +134,18 @@ class MultiTVSitesTestCase(TestCase):
self.assertEqual(p2.item.imdb, p3.item.imdb)
self.assertEqual(p1.item.id, p2.item.id)
self.assertEqual(p2.item.id, p3.item.id)
class MovieTVModelRecastTestCase(TestCase):
@use_local_response
def test_recast(self):
from catalog.models import Movie, TVShow
url2 = "https://www.imdb.com/title/tt0436992/"
p2 = SiteManager.get_site_by_url(url2).get_resource_ready()
tv = p2.item
self.assertEqual(tv.class_name, "tvshow")
self.assertEqual(tv.title, "神秘博士")
movie = tv.recast_to(Movie)
self.assertEqual(movie.class_name, "movie")
self.assertEqual(movie.title, "神秘博士")

View file

@ -51,6 +51,13 @@ urlpatterns = [
merge,
name="merge",
),
re_path(
r"^(?P<item_path>"
+ _get_all_url_paths()
+ ")/(?P<item_uuid>[A-Za-z0-9]{21,22})/recast$",
recast,
name="recast",
),
re_path(
r"^(?P<item_path>"
+ _get_all_url_paths()

View file

@ -17,7 +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.models import ExternalResource, ItemCategory
from catalog.common.sites import AbstractSite, SiteManager
from mastodon import mastodon_request_included
from mastodon.models import MastodonApplication
@ -149,14 +149,7 @@ def edit(request, item_path, item_uuid):
if item.external_resources.all().count() > 0:
form.fields["primary_lookup_id_type"].disabled = True
form.fields["primary_lookup_id_value"].disabled = True
return render(
request,
"catalog_edit.html",
{
"form": form,
"item": item,
},
)
return render(request, "catalog_edit.html", {"form": form, "item": item})
elif request.method == "POST":
item = get_object_or_404(Item, uid=base62.decode(item_uuid))
form_cls = CatalogForms[item.__class__.__name__]
@ -192,6 +185,21 @@ def delete(request, item_path, item_uuid):
)
@login_required
def recast(request, item_path, item_uuid):
if request.method != "POST":
return HttpResponseBadRequest()
if not request.user.is_staff:
raise PermissionDenied()
item = get_object_or_404(Item, uid=base62.decode(item_uuid))
cls = request.POST.get("class")
model = TVShow if cls == "tvshow" else (Movie if cls == "movie" else None)
if not model:
return HttpResponseBadRequest("invalid class")
new_item = item.recast_to(model)
return redirect(new_item.url)
@login_required
def unlink(request):
if request.method != "POST":

View file

@ -32,7 +32,7 @@
<a class="navbar__link {% if current == 'data' %}current{% endif %}" href="{% url 'users:data' %}">{% trans '数据' %}</a>
<a class="navbar__link {% if current == 'preferences' %}current{% endif %}" href="{% url 'users:preferences' %}">{% trans '设置' %}</a>
<a class="navbar__link" id="logoutLink" href="{% url 'users:logout' %}">{% trans '登出' %}</a>
{% if request.user.is_staff %}
{% if request.user.is_superuser %}
<a class="navbar__link" href="{% admin_url %}">{% trans '后台' %}</a>
{% endif %}