recast
This commit is contained in:
parent
2da1991025
commit
d2bfbb727f
9 changed files with 77 additions and 24 deletions
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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?');">
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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, "神秘博士")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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 %}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue