use json format for crew & actors

This commit is contained in:
Your Name 2023-06-05 17:22:34 -04:00 committed by Henri Dickson
parent 26c8b42e64
commit 6c9dd620f3
8 changed files with 113 additions and 23 deletions

View file

@ -1,8 +1,35 @@
from catalog.common import *
from functools import cached_property
from django.utils.translation import gettext_lazy as _
from django.db import models
from catalog.common import *
from catalog.common.utils import DEFAULT_ITEM_COVER
from functools import cached_property
_CREW_SCHEMA = {
"type": "list",
"items": {
"type": "dict",
"keys": {
"name": {"type": "string", "title": _("名字")},
"role": {"type": "string", "title": _("职能")},
},
"required": ["role", "name"],
},
"uniqueItems": True,
}
_ACTOR_SCHEMA = {
"type": "list",
"items": {
"type": "dict",
"keys": {
"name": {"type": "string", "title": _("名字"), "placeholder": _("演员名字,必填")},
"role": {"type": "string", "title": _("角色"), "placeholder": _("也可不填写")},
},
"required": ["name"],
},
"uniqueItems": True,
}
class Performance(Item):
@ -69,8 +96,15 @@ class Performance(Item):
blank=True,
default=list,
)
performer = jsondata.ArrayField(
actor = jsondata.JSONField(
verbose_name=_("演员"),
null=False,
blank=True,
default=list,
schema=_ACTOR_SCHEMA,
)
performer = jsondata.ArrayField(
verbose_name=_("表演者"),
base_field=models.CharField(blank=True, default="", max_length=500),
null=False,
blank=True,
@ -83,12 +117,12 @@ class Performance(Item):
blank=True,
default=list,
)
crew = jsondata.ArrayField(
crew = jsondata.JSONField(
verbose_name=_("其他演职人员和团体"),
base_field=models.CharField(blank=True, default="", max_length=500),
null=False,
blank=True,
default=list,
schema=_CREW_SCHEMA,
)
location = jsondata.ArrayField(
verbose_name=_("剧场空间"),
@ -98,7 +132,10 @@ class Performance(Item):
default=list,
)
opening_date = jsondata.CharField(
verbose_name=_("首演日期"), max_length=100, null=True, blank=True
verbose_name=_("首演日期"),
max_length=100,
null=True,
blank=True,
)
closing_date = jsondata.CharField(
verbose_name=_("结束日期"), max_length=100, null=True, blank=True
@ -122,6 +159,7 @@ class Performance(Item):
"orig_creator",
"composer",
"choreographer",
"actor",
"performer",
"crew",
"official_site",
@ -196,8 +234,15 @@ class PerformanceProduction(Item):
blank=True,
default=list,
)
performer = jsondata.ArrayField(
actor = jsondata.JSONField(
verbose_name=_("演员"),
null=False,
blank=True,
default=list,
schema=_ACTOR_SCHEMA,
)
performer = jsondata.ArrayField(
verbose_name=_("表演者"),
base_field=models.CharField(blank=True, default="", max_length=500),
null=False,
blank=True,
@ -210,12 +255,12 @@ class PerformanceProduction(Item):
blank=True,
default=list,
)
crew = jsondata.ArrayField(
crew = jsondata.JSONField(
verbose_name=_("其他演职人员和团体"),
base_field=models.CharField(blank=True, default="", max_length=500),
null=False,
blank=True,
default=list,
schema=_CREW_SCHEMA,
)
location = jsondata.ArrayField(
verbose_name=_("剧场空间"),
@ -248,6 +293,7 @@ class PerformanceProduction(Item):
"orig_creator",
"composer",
"choreographer",
"actor",
"performer",
"crew",
"official_site",

View file

@ -70,11 +70,31 @@ class DoubanDramaTestCase(TestCase):
# )
self.assertEqual(item.director, ["小池修一郎", "小池 修一郎", "石丸さち子"])
self.assertEqual(item.playwright, ["小池修一郎", "Baroness Orczy原作", "小池 修一郎"])
self.assertEqual(item.performer, ["安蘭けい", "柚希礼音", "遠野あすか", "霧矢大夢", "龍真咲"])
self.assertEqual(
item.actor,
[
{"name": "安蘭けい", "role": ""},
{"name": "柚希礼音", "role": ""},
{"name": "遠野あすか", "role": ""},
{"name": "霧矢大夢", "role": ""},
{"name": "龍真咲", "role": ""},
],
)
self.assertEqual(len(resource.related_resources), 4)
crawl_related_resources_task(resource.id) # force the async job to run now
productions = list(item.productions.all().order_by("title"))
self.assertEqual(len(productions), 4)
self.assertEqual(
productions[3].actor,
[
{"name": "石丸幹二", "role": "パーシー・ブレイクニー"},
{"name": "石井一孝", "role": "ショーヴラン"},
{"name": "安蘭けい", "role": "マルグリット・サン・ジュスト"},
{"name": "上原理生", "role": ""},
{"name": "泉見洋平", "role": ""},
{"name": "松下洸平", "role": "アルマン"},
],
)
self.assertEqual(productions[0].opening_date, "2008-06-20")
self.assertEqual(productions[0].closing_date, "2008-08-04")
self.assertEqual(productions[2].opening_date, "2017-03-10")
@ -82,7 +102,7 @@ class DoubanDramaTestCase(TestCase):
self.assertEqual(productions[3].opening_date, "2017-11-13")
self.assertEqual(productions[3].closing_date, None)
self.assertEqual(productions[3].title, "ミュージカル2017年")
self.assertEqual(len(productions[3].performer), 6)
self.assertEqual(len(productions[3].actor), 6)
self.assertEqual(productions[3].language, ["日语"])
self.assertEqual(productions[3].opening_date, "2017-11-13")
self.assertEqual(productions[3].location, ["梅田芸術劇場メインホール"])

View file

@ -63,7 +63,7 @@ class DoubanDramaVersion(AbstractSite):
"title": title,
"director": [x.strip() for x in h.xpath(q.format("导演"))],
"playwright": [x.strip() for x in h.xpath(q.format("编剧"))],
"performer": [x.strip() for x in h.xpath(q.format("主演"))],
# "actor": [x.strip() for x in h.xpath(q.format("主演"))],
"composer": [x.strip() for x in h.xpath(q.format("作曲"))],
"language": [x.strip() for x in h.xpath(q2.format("语言"))],
"opening_date": " ".join(h.xpath(q2.format("演出日期"))).strip(),
@ -76,6 +76,14 @@ class DoubanDramaVersion(AbstractSite):
if l > 3:
data["opening_date"] = "-".join(d[:3])
data["closing_date"] = "-".join(d[0 : 6 - l] + d[3:l])
actor_elem = h.xpath(p + "//dt[text()='主演:']/following-sibling::dd[1]/a")
data["actor"] = []
for e in actor_elem:
n = "".join(e.xpath("span/text()")).strip()
t = "".join(e.xpath("following-sibling::text()[1]")).strip()
t = re.sub(r"^[\s\(饰]*(.+)\)[\s\/]*$", r"\1", t).strip()
t = t if t != "/" else ""
data["actor"].append({"name": n, "role": t})
img_url_elem = h.xpath("//img[@itemprop='image']/@src")
data["cover_image_url"] = img_url_elem[0].strip() if img_url_elem else None
pd = ResourceContent(metadata=data)
@ -184,8 +192,8 @@ class DoubanDrama(AbstractSite):
"//div[@class='meta']/dl//dt[text()='编剧:']/following-sibling::dd/a[@itemprop='author']//text()"
)
]
data["performer"] = [
s.strip()
data["actor"] = [
{"name": s.strip(), "role": ""}
for s in h.xpath(
"//div[@class='meta']/dl//dt[text()='主演:']/following-sibling::dd/a[@itemprop='actor']//text()"
)

View file

@ -25,10 +25,11 @@
<div>{% include '_people.html' with people=item.orig_creator role='原作' max=5 %}</div>
<div>{% include '_people.html' with people=item.director role='导演' max=5 %}</div>
<div>{% include '_people.html' with people=item.playwright role='编剧' max=5 %}</div>
<div>{% include '_people.html' with people=item.performer role='演员' max=10 %}</div>
<div>{% include '_crew.html' with people=item.actor role='演员' max=10 %}</div>
<div>{% include '_people.html' with people=item.performer role='表演者' max=10 %}</div>
<div>{% include '_people.html' with people=item.composer role='作曲' max=5 %}</div>
<div>{% include '_people.html' with people=item.choreographer role='编舞' max=5 %}</div>
<div>{% include '_people.html' with people=item.crew role='演职人员' max=10 %}</div>
<div>{% include '_crew.html' with people=item.crew role='演职人员' max=10 %}</div>
<div>
{% if item.official_site %}
{% trans '官方网站' %} <span>{{ item.official_site|urlizetrunc:24 }}</span>
@ -58,10 +59,11 @@
{% include '_people.html' with people=prod.orig_creator role='原作' max=2 %}
{% include '_people.html' with people=prod.director role='导演' max=2 %}
{% include '_people.html' with people=prod.playwright role='编剧' max=2 %}
{% include '_people.html' with people=prod.performer role='演员' max=5 %}
{% include '_crew.html' with people=prod.actor role='演员' max=5 %}
{% include '_people.html' with people=prod.performer role='表演者' max=5 %}
{% include '_people.html' with people=prod.composer role='作曲' max=2 %}
{% include '_people.html' with people=prod.choreographer role='编舞' max=2 %}
{% include '_people.html' with people=prod.crew role='演职人员' max=5 %}
{% include '_crew.html' with people=prod.crew role='演职人员' max=5 %}
</div>
</hgroup>
{% endfor %}

View file

@ -30,10 +30,11 @@
<div>{% include '_people.html' with people=item.orig_creator role='原作' max=5 %}</div>
<div>{% include '_people.html' with people=item.director role='导演' max=5 %}</div>
<div>{% include '_people.html' with people=item.playwright role='编剧' max=5 %}</div>
<div>{% include '_people.html' with people=item.performer role='演员' max=10 %}</div>
<div>{% include '_crew.html' with people=item.actor role='演员' max=50 %}</div>
<div>{% include '_people.html' with people=item.performer role='表演者' max=50 %}</div>
<div>{% include '_people.html' with people=item.composer role='作曲' max=5 %}</div>
<div>{% include '_people.html' with people=item.choreographer role='编舞' max=5 %}</div>
<div>{% include '_people.html' with people=item.crew role='演职人员' max=10 %}</div>
<div>{% include '_crew.html' with people=item.crew role='演职人员' max=50 %}</div>
<div>
{% if item.official_site %}
{% trans '官方网站' %} <span>{{ item.official_site|urlizetrunc:24 }}</span>

View file

@ -183,7 +183,14 @@ def edit(request, item_path, item_uuid):
form.instance.save()
return redirect(form.instance.url)
else:
raise BadRequest(form.errors)
e = form.errors
e.additonal_detail = []
for f, v in e.as_data().items():
for validation_error in v:
if hasattr(validation_error, "error_map"):
for f2, v2 in validation_error.error_map.items():
e.additonal_detail.append(f"{f}§{f2}: {'; '.join(v2)}")
raise BadRequest(e)
else:
raise BadRequest()

View file

@ -21,8 +21,13 @@
<header>
<h3>🤦🏻 无效的请求</h3>
</header>
{{ exception }}
您可能提交了无效的数据,或者相关内容已被作者删除。如果您确信这是我们的错误,请通过页面底部的链接联系我们。
<section>
{{ exception }}
{% if exception.additonal_detail %}
{% for e in exception.additonal_detail %}<p>{{ e }}</p>{% endfor %}
{% endif %}
</section>
</article>
</main>
{% include "partial/_footer.html" %}

View file

@ -14,7 +14,8 @@
<div>{% include '_people.html' with people=item.other_title role='又名' max=2 %}</div>
<div>{% include '_people.html' with people=item.director role='导演' max=2 %}</div>
<div>{% include '_people.html' with people=item.playwright role='编剧' max=2 %}</div>
<div>{% include '_people.html' with people=item.performer role='演员' max=5 %}</div>
<div>{% include '_people.html' with people=item.actor role='演员' max=5 %}</div>
<div>{% include '_people.html' with people=item.performer role='表演者' max=5 %}</div>
<div>{% include '_people.html' with people=item.composer role='作曲' max=2 %}</div>
<div>{% include '_people.html' with people=item.choreographer role='编舞' max=2 %}</div>
<div>{% include '_people.html' with people=item.crew role='演职人员' max=2 %}</div>