finish independent movie app
This commit is contained in:
parent
ac9289c289
commit
8fd0788047
47 changed files with 947 additions and 220 deletions
|
@ -1,11 +1,8 @@
|
|||
from django import forms
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from .models import Book, BookMark, BookReview
|
||||
from common.models import MarkStatusEnum
|
||||
from common.forms import RadioBooleanField, RatingValidator, TagField, TagInput
|
||||
from common.forms import KeyValueInput
|
||||
from common.forms import PreviewImageInput
|
||||
from common.forms import *
|
||||
|
||||
|
||||
def BookMarkStatusTranslator(status):
|
||||
|
@ -21,6 +18,7 @@ class BookForm(forms.ModelForm):
|
|||
pub_year = forms.IntegerField(required=False, max_value=9999, min_value=0, label=_("出版年份"))
|
||||
pub_month = forms.IntegerField(required=False, max_value=12, min_value=1, label=_("出版月份"))
|
||||
id = forms.IntegerField(required=False, widget=forms.HiddenInput())
|
||||
other_info = JSONField(required=False, label=_("其他信息"))
|
||||
class Meta:
|
||||
model = Book
|
||||
fields = [
|
||||
|
@ -66,7 +64,6 @@ class BookForm(forms.ModelForm):
|
|||
widgets = {
|
||||
'author': forms.TextInput(attrs={'placeholder': _("多个作者使用英文逗号分隔")}),
|
||||
'translator': forms.TextInput(attrs={'placeholder': _("多个译者使用英文逗号分隔")}),
|
||||
'other_info': KeyValueInput(),
|
||||
# 'cover': forms.FileInput(),
|
||||
'cover': PreviewImageInput(),
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ title }}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ title }}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<!-- <link rel="stylesheet" href="{% static 'lib/css/milligram.css' %}"> -->
|
||||
<!-- <link rel="stylesheet" href="{% static 'css/boofilsic_edit.css' %}"> -->
|
||||
|
@ -27,6 +27,7 @@
|
|||
<div class="single-section-wrapper" id="main">
|
||||
<form class="entity-form" action="{{ submit_url }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.media }}
|
||||
{{ form }}
|
||||
<input class="button" type="submit" value="{% trans '提交' %}">
|
||||
</form>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ title }}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ title }}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/create_update_review.js' %}"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 删除图书' %}</title>
|
||||
<title>{% trans 'NiceDB - 删除图书' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 删除评论' %}</title>
|
||||
<title>{% trans 'NiceDB - 删除评论' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="{% static 'lib/css/rating-star.css' %}">
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<meta property="og:type" content="book">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:image" content="{{ request.scheme }}://{{ request.get_host }}{{ book.cover.url }}">
|
||||
<meta property="og:site_name" content="NiceDB">
|
||||
{% if book.author %}
|
||||
<meta property="og:book:author" content="{% for author in book.author %}{{ author }}{% if not forloop.last %},{% endif %}{% endfor %}">
|
||||
{% endif %}
|
||||
|
@ -21,7 +22,7 @@
|
|||
<meta property="og:book:isbn" content="{{ book.isbn }}">
|
||||
{% endif %}
|
||||
|
||||
<title>{% trans 'Nicedb - 书籍详情' %} | {{ book.title }}</title>
|
||||
<title>{% trans 'NiceDB - 书籍详情' %} | {{ book.title }}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/detail.js' %}"></script>
|
||||
|
@ -62,14 +63,14 @@
|
|||
<div>{% if book.isbn %}{% trans 'ISBN:' %}{{ book.isbn }}{% endif %}</div>
|
||||
<div>{% if book.author %}{% trans '作者:' %}
|
||||
{% for author in book.author %}
|
||||
<span>{{ author }}</span>
|
||||
<span>{{ author }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if book.pub_house %}{% trans '出版社:' %}{{ book.pub_house }}{% endif %}</div>
|
||||
<div>{% if book.subtitle %}{% trans '副标题:' %}{{ book.subtitle }}{% endif %}</div>
|
||||
<div>{% if book.translator %}{% trans '译者:' %}
|
||||
{% for translator in book.translator %}
|
||||
<span>{{ translator }}</span>
|
||||
<span>{{ translator }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if book.orig_title %}{% trans '原作名:' %}{{ book.orig_title }}{% endif %}</div>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ user.username }}{{ list_title }}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ user.username }}{{ list_title }}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ book.title }}{% trans '的标记' %}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ book.title }}{% trans '的标记' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<meta property="og:article:author" content="{{ review.owner.username }}">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:image" content="{{ request.scheme }}://{{ request.get_host }}{% static 'img/logo_square.svg' %}">
|
||||
<title>{% trans 'Nicedb - 评论详情' %}</title>
|
||||
<title>{% trans 'NiceDB - 评论详情' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ book.title }}{% trans '的评论' %}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ book.title }}{% trans '的评论' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 从豆瓣获取数据' %}</title>
|
||||
<title>{% trans 'NiceDB - 从豆瓣获取数据' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/scrape.js' %}"></script>
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic.css' %}">
|
||||
|
@ -68,6 +68,7 @@ ISBN: 9787020104345
|
|||
<div id="scrapeForm">
|
||||
<form action="{% url 'books:create' %}" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.media }}
|
||||
{{ form }}
|
||||
</form>
|
||||
<a href="{% url 'books:scrape' %}" class="button add-button submit">{% trans '剽取!' %}</a>
|
||||
|
@ -97,7 +98,10 @@ ISBN: 9787020104345
|
|||
|
||||
</div>
|
||||
<script>
|
||||
|
||||
// mark required
|
||||
$("#content input[required]").each(function () {
|
||||
$(this).prev().prepend("*");
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ def retrieve(request, id):
|
|||
except ObjectDoesNotExist:
|
||||
mark = None
|
||||
if mark:
|
||||
mark_tags = mark.mark_tags.all()
|
||||
mark_tags = mark.bookmark_tags.all()
|
||||
mark.get_status_display = BookMarkStatusTranslator(mark.status)
|
||||
mark_form = BookMarkForm(instance=mark, initial={
|
||||
'tags': mark_tags
|
||||
|
@ -239,7 +239,7 @@ def create_update_mark(request):
|
|||
if pk:
|
||||
mark = get_object_or_404(BookMark, pk=pk)
|
||||
old_rating = mark.rating
|
||||
old_tags = mark.mark_tags.all()
|
||||
old_tags = mark.bookmark_tags.all()
|
||||
# update
|
||||
form = BookMarkForm(request.POST, instance=mark)
|
||||
else:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django import forms
|
||||
from django.contrib.postgres.forms import JSONField
|
||||
import django.contrib.postgres.forms as postgres
|
||||
from django.utils import formats
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import json
|
||||
|
@ -26,6 +27,21 @@ class KeyValueInput(forms.Widget):
|
|||
context['widget']['keyvalue_pairs'] = key_value_pairs
|
||||
return context
|
||||
|
||||
class Media:
|
||||
js = ('js/key_value_input.js',)
|
||||
|
||||
|
||||
class JSONField(postgres.JSONField):
|
||||
widget = KeyValueInput
|
||||
def to_python(self, value):
|
||||
if not value:
|
||||
return None
|
||||
json = {}
|
||||
pairs = eval(value)
|
||||
for pair in pairs:
|
||||
json = {**json, **pair}
|
||||
return super().to_python(json)
|
||||
|
||||
|
||||
class RadioBooleanField(forms.ChoiceField):
|
||||
widget = forms.RadioSelect
|
||||
|
@ -110,3 +126,35 @@ class TagField(forms.CharField):
|
|||
if not value:
|
||||
return
|
||||
return [t.strip() for t in value.split(',')]
|
||||
|
||||
|
||||
class MultiSelect(forms.SelectMultiple):
|
||||
template_name = 'widgets/multi_select.html'
|
||||
|
||||
|
||||
class HstoreInput(forms.Widget):
|
||||
template_name = 'widgets/hstore.html'
|
||||
|
||||
def format_value(self, value):
|
||||
"""
|
||||
Return a value as it should appear when rendered in a template.
|
||||
"""
|
||||
if value == '' or value is None:
|
||||
return None
|
||||
if self.is_localized:
|
||||
return formats.localize_input(value)
|
||||
return value
|
||||
|
||||
class Media:
|
||||
js = ('js/key_value_input.js',)
|
||||
|
||||
|
||||
class HstoreField(forms.CharField):
|
||||
widget = HstoreInput
|
||||
def to_python(self, value):
|
||||
if not value:
|
||||
return None
|
||||
pairs = eval(value)
|
||||
if len(pairs) == 1:
|
||||
pairs = (pairs,)
|
||||
return pairs
|
||||
|
|
|
@ -300,7 +300,7 @@ def scrape_douban_movie(url):
|
|||
if duration_elem:
|
||||
duration = duration_elem[0].strip()
|
||||
if other_duration_elem:
|
||||
duration += other_duration_elem[0]
|
||||
duration += other_duration_elem[0].rstrip()
|
||||
else:
|
||||
duration = None
|
||||
|
||||
|
@ -324,7 +324,7 @@ def scrape_douban_movie(url):
|
|||
is_series = True if episodes else False
|
||||
|
||||
brief_elem = content.xpath("//span[@property='v:summary']/text()")
|
||||
brief = brief[0].strip() if brief_elem else None
|
||||
brief = brief_elem[0].strip() if brief_elem else None
|
||||
|
||||
img_url_elem = content.xpath("//img[@rel='v:image']/@src")
|
||||
img_url = img_url_elem[0].strip() if img_url_elem else None
|
||||
|
|
|
@ -1193,10 +1193,15 @@ select::placeholder {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.entity-detail .entity-detail__title--secondary {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.entity-detail .entity-detail__fields {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 48%;
|
||||
width: 46%;
|
||||
margin-left: 2%;
|
||||
}
|
||||
|
||||
.entity-detail .entity-detail__fields div, .entity-detail .entity-detail__fields span {
|
||||
|
@ -2083,3 +2088,44 @@ select::placeholder {
|
|||
.rating-star .jq-star {
|
||||
cursor: unset !important;
|
||||
}
|
||||
|
||||
.ms-parent > .ms-choice {
|
||||
margin-bottom: 1.5rem;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: transparent;
|
||||
border: 0.1rem solid #ccc;
|
||||
border-radius: .4rem;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
-webkit-box-sizing: inherit;
|
||||
box-sizing: inherit;
|
||||
padding: .6rem 1.0rem;
|
||||
width: 100%;
|
||||
height: 30.126px;
|
||||
}
|
||||
|
||||
.ms-parent > .ms-choice:focus {
|
||||
border-color: #00a1cc;
|
||||
}
|
||||
|
||||
.ms-parent > .ms-choice > .icon-caret {
|
||||
top: 15.5px;
|
||||
}
|
||||
|
||||
.ms-parent > .ms-choice > span {
|
||||
color: black;
|
||||
font-weight: initial;
|
||||
font-size: 13.3333px;
|
||||
top: 2.5px;
|
||||
left: 2px;
|
||||
}
|
||||
|
||||
.ms-parent > .ms-choice > span:hover, .ms-parent > .ms-choice > span:focus {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.ms-parent > .ms-drop > ul > li > label > span {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
|
63
common/static/js/key_value_input.js
Normal file
63
common/static/js/key_value_input.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
function keyValueInput(valueKeyWidget, hiddenInput) {
|
||||
let placeholderKey = valueKeyWidget.attr('placeholder-key');
|
||||
let placeholderValue = valueKeyWidget.attr('placeholder-value');
|
||||
if (placeholderKey == null) {
|
||||
placeholderKey = '';
|
||||
}
|
||||
|
||||
if (placeholderValue == null) {
|
||||
placeholderValue = '';
|
||||
}
|
||||
|
||||
let newInputPair = $('<input type="text"' + 'placeholder=' + placeholderKey + '><input type="text"' + 'placeholder=' + placeholderValue + '>');
|
||||
valueKeyWidget.append(newInputPair.clone());
|
||||
// add new input pair
|
||||
valueKeyWidget.on('input', ':nth-last-child(1)', function () {
|
||||
if ($(this).val() && $(this).prev().val()) {
|
||||
valueKeyWidget.append($(newInputPair).clone());
|
||||
}
|
||||
});
|
||||
valueKeyWidget.on('input', ':nth-last-child(2)', function () {
|
||||
if ($(this).val() && $(this).next().val()) {
|
||||
valueKeyWidget.append($(newInputPair).clone());
|
||||
}
|
||||
});
|
||||
valueKeyWidget.on('input', ':nth-last-child(4)', function () {
|
||||
if (!$(this).val() && !$(this).next().val() && valueKeyWidget.children("input").length > 2) {
|
||||
$(this).next().remove();
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
valueKeyWidget.on('input', ':nth-last-child(3)', function () {
|
||||
if (!$(this).val() && !$(this).prev().val() && valueKeyWidget.children("input").length > 2) {
|
||||
$(this).prev().remove();
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
valueKeyWidget.on('input', function () {
|
||||
let keys = $(this).children(":nth-child(odd)").map(function () {
|
||||
if ($(this).val()) {
|
||||
return $(this).val();
|
||||
}
|
||||
}).get();
|
||||
let values = $(this).children(":nth-child(even)").map(function () {
|
||||
if ($(this).val()) {
|
||||
return $(this).val();
|
||||
}
|
||||
}).get();
|
||||
if (keys.length == values.length) {
|
||||
let finalValue = [];
|
||||
keys.forEach(function (key, i) {
|
||||
let json = new Object;
|
||||
json[key] = values[i];
|
||||
finalValue.push(JSON.stringify(json))
|
||||
});
|
||||
hiddenInput.val(finalValue.toString());
|
||||
} else {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
$color-initial: #fff !default
|
||||
$color-primary: #00a1cc !default
|
||||
$color-secondary: #606c76 !default
|
||||
$color-tertiary: #fff !default
|
||||
$color-tertiary: #bbb !default
|
||||
$color-quaternary: #d5d5d5 !default
|
||||
$color-quinary: #e5e5e5 !default
|
||||
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
|
||||
hr
|
||||
border: 0
|
||||
border-top: .1rem solid $color-tertiary
|
||||
border-top: .1rem solid $color-initial
|
||||
margin: 3.0rem 0
|
||||
|
|
|
@ -106,11 +106,15 @@ $sub-section-title-margin: 8px
|
|||
|
||||
& &__title
|
||||
font-weight: bold
|
||||
|
||||
& &__title--secondary
|
||||
color: $color-tertiary
|
||||
|
||||
& &__fields
|
||||
display: inline-block
|
||||
vertical-align: top
|
||||
width: 48%
|
||||
width: 46%
|
||||
margin-left: 2%
|
||||
// margin-bottom: 5px
|
||||
& div, & span
|
||||
margin: 1px 0
|
||||
|
|
|
@ -2,4 +2,35 @@
|
|||
min-height: 100px
|
||||
|
||||
.rating-star .jq-star
|
||||
cursor: unset !important
|
||||
cursor: unset !important
|
||||
|
||||
.ms-parent > .ms-choice
|
||||
margin-bottom: 1.5rem
|
||||
appearance: none
|
||||
background-color: transparent
|
||||
border: 0.1rem solid #ccc
|
||||
border-radius: .4rem
|
||||
box-shadow: none
|
||||
box-sizing: inherit
|
||||
padding: .6rem 1.0rem
|
||||
width: 100%
|
||||
height: 30.126px
|
||||
|
||||
&:focus
|
||||
border-color: $color-primary
|
||||
|
||||
& > .icon-caret
|
||||
top: 15.5px
|
||||
|
||||
& > span
|
||||
color: black
|
||||
font-weight: initial
|
||||
// font-size: 1.3rem
|
||||
font-size: 13.3333px
|
||||
top: 2.5px
|
||||
left: 2px
|
||||
&:hover, &:focus
|
||||
color: black
|
||||
|
||||
.ms-parent > .ms-drop > ul > li > label > span
|
||||
margin-left: 10px
|
|
@ -10,7 +10,13 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 主页' %}</title>
|
||||
|
||||
{% if user == request.user %}
|
||||
<title>{% trans 'NiceDB - 我的主页' %}</title>
|
||||
{% else %}
|
||||
<title>{% trans 'NiceDB - ' %}{{user.username}}{% trans '的主页' %}</title>
|
||||
{% endif %}
|
||||
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/mastodon.js' %}"></script>
|
||||
<script src="{% static 'js/home.js' %}"></script>
|
||||
|
@ -109,6 +115,84 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="entity-sort" id="movieWish">
|
||||
<h5 class="entity-sort__label">
|
||||
{% trans '想看的电影/剧集' %}
|
||||
</h5>
|
||||
{% if wish_movies_more %}
|
||||
<a href="{% url 'users:movie_list' user.id 'wish' %}"
|
||||
class="entity-sort__more-link">{% trans '更多' %}</a>
|
||||
{% endif %}
|
||||
|
||||
<ul class="entity-sort__entity-list">
|
||||
{% for wish_movie_mark in wish_movie_marks %}
|
||||
<li class="entity-sort__entity">
|
||||
|
||||
<a href="{% url 'movies:retrieve' wish_movie_mark.movie.id %}">
|
||||
<img src="{{ wish_movie_mark.movie.cover.url }}"
|
||||
alt="{{wish_movie_mark.movie.title}}" class="entity-sort__entity-img">
|
||||
<div class="entity-sort__entity-name" title="wish_movie_mark.movie.title">
|
||||
{{ wish_movie_mark.movie.title }}</div>
|
||||
</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<div>暂无记录</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="entity-sort" id="movieWish">
|
||||
<h5 class="entity-sort__label">
|
||||
{% trans '在看的电影/剧集' %}
|
||||
</h5>
|
||||
{% if do_movies_more %}
|
||||
<a href="{% url 'users:movie_list' user.id 'do' %}"
|
||||
class="entity-sort__more-link">{% trans '更多' %}</a>
|
||||
{% endif %}
|
||||
|
||||
<ul class="entity-sort__entity-list">
|
||||
{% for do_movie_mark in do_movie_marks %}
|
||||
<li class="entity-sort__entity">
|
||||
|
||||
<a href="{% url 'movies:retrieve' do_movie_mark.movie.id %}">
|
||||
<img src="{{ do_movie_mark.movie.cover.url }}"
|
||||
alt="{{do_movie_mark.movie.title}}" class="entity-sort__entity-img">
|
||||
<div class="entity-sort__entity-name" title="{{do_movie_mark.movie.title}}">
|
||||
{{ do_movie_mark.movie.title }}</div>
|
||||
</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<div>暂无记录</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="entity-sort" id="movieCollect">
|
||||
<h5 class="entity-sort__label">
|
||||
{% trans '看过的电影/剧集' %}
|
||||
</h5>
|
||||
{% if collect_movies_more %}
|
||||
<a href="{% url 'users:movie_list' user.id 'collect' %}"
|
||||
class="entity-sort__more-link">{% trans '更多' %}</a>
|
||||
{% endif %}
|
||||
|
||||
<ul class="entity-sort__entity-list">
|
||||
{% for collect_movie_mark in collect_movie_marks %}
|
||||
<li class="entity-sort__entity">
|
||||
|
||||
<a href="{% url 'movies:retrieve' collect_movie_mark.movie.id %}">
|
||||
<img src="{{ collect_movie_mark.movie.cover.url }}"
|
||||
alt="{{collect_movie_mark.movie.title}}" class="entity-sort__entity-img">
|
||||
<span class="entity-sort__entity-name"
|
||||
title="{{collect_movie_mark.movie.title}}">{{ collect_movie_mark.movie.title }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<div>暂无记录</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 搜索结果' %}</title>
|
||||
<title>{% trans 'NiceDB - 搜索结果' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
|
31
common/templates/widgets/hstore.html
Normal file
31
common/templates/widgets/hstore.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
<style>
|
||||
.widget-value-key-input input:nth-child(odd) {
|
||||
width: 49%;
|
||||
margin-right: 1%;
|
||||
}
|
||||
|
||||
.widget-value-key-input input:nth-child(even) {
|
||||
width: 49%;
|
||||
margin-left: 1%;
|
||||
}
|
||||
</style>
|
||||
<div class="widget-value-key-input" name='{{ widget.name }}'{% include "django/forms/widgets/attrs.html" %}>
|
||||
{% if widget.value != None %}
|
||||
|
||||
{% for pair in widget.value %}
|
||||
|
||||
{% for k, v in pair.items %}
|
||||
<input type="text" value="{{ k }}"><input type="text" value="{{ v }}">
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
<input type="text" class="widget-value-key-input-data" hidden name="{{ widget.name }}">
|
||||
<script>
|
||||
keyValueInput(
|
||||
$(".widget-value-key-input[name='{{ widget.name }}']"),
|
||||
$(".widget-value-key-input-data[name='{{ widget.name }}']")
|
||||
);
|
||||
</script>
|
|
@ -8,7 +8,7 @@
|
|||
margin-left: 1%;
|
||||
}
|
||||
</style>
|
||||
<div class="widget-value-key-input">
|
||||
<div class="widget-value-key-input" name='{{ widget.name }}'{% include "django/forms/widgets/attrs.html" %}>
|
||||
{% if widget.value != None %}
|
||||
|
||||
{% for k, v in widget.keyvalue_pairs.items %}
|
||||
|
@ -19,53 +19,8 @@
|
|||
</div>
|
||||
<input type="text" class="widget-value-key-input-data" hidden name="{{ widget.name }}">
|
||||
<script>
|
||||
//init
|
||||
$(".widget-value-key-input").append('<input type="text"><input type="text">');
|
||||
// add new input pair
|
||||
$(".widget-value-key-input").on('input', ':nth-last-child(1)', function() {
|
||||
let newInputPair = $('<input type="text"><input type="text">');
|
||||
if ($(this).val() && $(this).prev().val()) {
|
||||
$(".widget-value-key-input").append($(newInputPair).clone());
|
||||
}
|
||||
});
|
||||
$(".widget-value-key-input").on('input', ':nth-last-child(2)', function() {
|
||||
let newInputPair = $('<input type="text"><input type="text">');
|
||||
if ($(this).val() && $(this).next().val()) {
|
||||
$(".widget-value-key-input").append($(newInputPair).clone());
|
||||
}
|
||||
});
|
||||
$(".widget-value-key-input").on('input', ':nth-last-child(4)', function() {
|
||||
if (!$(this).val() && !$(this).next().val() && $(".widget-value-key-input input").length > 2) {
|
||||
$(this).next().remove();
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
$(".widget-value-key-input").on('input', ':nth-last-child(3)', function() {
|
||||
if (!$(this).val() && !$(this).prev().val() && $(".widget-value-key-input input").length > 2) {
|
||||
$(this).prev().remove();
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
$(".widget-value-key-input").on('input', function() {
|
||||
let keys = $(this).children(":nth-child(odd)").map(function() {
|
||||
if ($(this).val()) {
|
||||
return $(this).val();
|
||||
}
|
||||
}).get();
|
||||
let values = $(this).children(":nth-child(even)").map(function() {
|
||||
if ($(this).val()) {
|
||||
return $(this).val();
|
||||
}
|
||||
}).get();
|
||||
if (keys.length == values.length) {
|
||||
let json = new Object;
|
||||
keys.forEach(function(key, i) {
|
||||
json[key] = values[i];
|
||||
});
|
||||
$("input.widget-value-key-input-data").val(JSON.stringify(json));
|
||||
} else {
|
||||
|
||||
}
|
||||
});
|
||||
keyValueInput(
|
||||
$(".widget-value-key-input[name='{{ widget.name }}']"),
|
||||
$(".widget-value-key-input-data[name='{{ widget.name }}']")
|
||||
);
|
||||
</script>
|
18
common/templates/widgets/multi_select.html
Normal file
18
common/templates/widgets/multi_select.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<select name="{{ widget.name }}"
|
||||
{% include "django/forms/widgets/attrs.html" %}>{% for group_name, group_choices, group_index in widget.optgroups %}{% if group_name %}
|
||||
<optgroup label="{{ group_name }}">{% endif %}{% for option in group_choices %}
|
||||
{% include option.template_name with widget=option %}{% endfor %}{% if group_name %}
|
||||
</optgroup>{% endif %}{% endfor %}
|
||||
</select>
|
||||
<link rel="stylesheet" href="https://unpkg.com/multiple-select@1.5.2/dist/multiple-select.min.css">
|
||||
<script src="https://unpkg.com/multiple-select@1.5.2/dist/multiple-select.min.js"></script>
|
||||
<script>
|
||||
$('select[name="{{ widget.name }}"]').multipleSelect({
|
||||
selectAll: false,
|
||||
width: "100%",
|
||||
displayTitle: true,
|
||||
// any value greater than number of genres
|
||||
minimumCountSelected: 50,
|
||||
filter: true,
|
||||
})
|
||||
</script>
|
|
@ -54,4 +54,12 @@ class PageLinksGenerator:
|
|||
self.first_page = 1
|
||||
self.last_page = total_pages
|
||||
self.page_range = range(self.start_page, self.end_page + 1)
|
||||
# assert self.has_prev is not None and self.has_next is not None
|
||||
# assert self.has_prev is not None and self.has_next is not None
|
||||
|
||||
|
||||
def ChoicesDictGenerator(choices_enum):
|
||||
choices_dict = {}
|
||||
for attr in dir(choices_enum):
|
||||
if not '__' in attr:
|
||||
choices_dict[getattr(choices_enum, attr).value] = getattr(choices_enum, attr).label
|
||||
return choices_dict
|
|
@ -12,6 +12,9 @@ from django.http import HttpResponseBadRequest
|
|||
# how many books have in each set at the home page
|
||||
BOOKS_PER_SET = 5
|
||||
|
||||
# how many movies have in each set at the home page
|
||||
MOVIES_PER_SET = 5
|
||||
|
||||
# how many items are showed in one search result page
|
||||
ITEMS_PER_PAGE = 20
|
||||
|
||||
|
@ -38,6 +41,19 @@ def home(request):
|
|||
status=MarkStatusEnum.COLLECT).order_by("-edited_time")
|
||||
collect_books_more = True if collect_book_marks.count() > BOOKS_PER_SET else False
|
||||
|
||||
|
||||
do_movie_marks = request.user.user_moviemarks.filter(
|
||||
status=MarkStatusEnum.DO).order_by("-edited_time")
|
||||
do_movies_more = True if do_movie_marks.count() > MOVIES_PER_SET else False
|
||||
|
||||
wish_movie_marks = request.user.user_moviemarks.filter(
|
||||
status=MarkStatusEnum.WISH).order_by("-edited_time")
|
||||
wish_movies_more = True if wish_movie_marks.count() > MOVIES_PER_SET else False
|
||||
|
||||
collect_movie_marks = request.user.user_moviemarks.filter(
|
||||
status=MarkStatusEnum.COLLECT).order_by("-edited_time")
|
||||
collect_movies_more = True if collect_movie_marks.count() > MOVIES_PER_SET else False
|
||||
|
||||
reports = Report.objects.order_by('-submitted_time').filter(is_read=False)
|
||||
# reports = Report.objects.latest('submitted_time').filter(is_read=False)
|
||||
|
||||
|
@ -51,6 +67,12 @@ def home(request):
|
|||
'do_books_more': do_books_more,
|
||||
'wish_books_more': wish_books_more,
|
||||
'collect_books_more': collect_books_more,
|
||||
'do_movie_marks': do_movie_marks[:MOVIES_PER_SET],
|
||||
'wish_movie_marks': wish_movie_marks[:MOVIES_PER_SET],
|
||||
'collect_movie_marks': collect_movie_marks[:MOVIES_PER_SET],
|
||||
'do_movies_more': do_movies_more,
|
||||
'wish_movies_more': wish_movies_more,
|
||||
'collect_movies_more': collect_movies_more,
|
||||
'reports': reports,
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
from django import forms
|
||||
from django.contrib.postgres.forms import SimpleArrayField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from .models import Movie, MovieMark, MovieReview
|
||||
from .models import Movie, MovieMark, MovieReview, MovieGenreEnum
|
||||
from common.models import MarkStatusEnum
|
||||
from common.forms import RadioBooleanField, RatingValidator, TagField, TagInput
|
||||
from common.forms import KeyValueInput
|
||||
from common.forms import PreviewImageInput
|
||||
from common.forms import *
|
||||
|
||||
|
||||
def MovieMarkStatusTranslator(status):
|
||||
|
@ -22,7 +20,24 @@ class MovieForm(forms.ModelForm):
|
|||
# required=False, max_value=9999, min_value=0, label=_("出版年份"))
|
||||
# pub_month = forms.IntegerField(
|
||||
# required=False, max_value=12, min_value=1, label=_("出版月份"))
|
||||
|
||||
id = forms.IntegerField(required=False, widget=forms.HiddenInput())
|
||||
genre = forms.MultipleChoiceField(
|
||||
choices=MovieGenreEnum.choices,
|
||||
widget= MultiSelect,
|
||||
label=_("类型")
|
||||
)
|
||||
showtime = HstoreField(
|
||||
required=False,
|
||||
label=_("上映时间"),
|
||||
widget=HstoreInput(
|
||||
attrs={
|
||||
'placeholder-key': _("日期"),
|
||||
'placeholder-value': _("地区"),
|
||||
}
|
||||
)
|
||||
)
|
||||
other_info = JSONField(required=False, label=_("其他信息"))
|
||||
|
||||
class Meta:
|
||||
model = Movie
|
||||
|
@ -31,7 +46,7 @@ class MovieForm(forms.ModelForm):
|
|||
'title',
|
||||
'orig_title',
|
||||
'other_title',
|
||||
'imbd_code',
|
||||
'imdb_code',
|
||||
'director',
|
||||
'playwright',
|
||||
'actor',
|
||||
|
@ -46,14 +61,15 @@ class MovieForm(forms.ModelForm):
|
|||
'episodes',
|
||||
'single_episode_length',
|
||||
'cover',
|
||||
'brief',
|
||||
'is_series',
|
||||
'brief',
|
||||
'other_info',
|
||||
]
|
||||
labels = {
|
||||
'title': _("标题"),
|
||||
'orig_title': _("原名"),
|
||||
'other_title': _("又名"),
|
||||
'imbd_code': _("IMBd编号"),
|
||||
'imdb_code': _("IMDb编号"),
|
||||
'director': _("导演"),
|
||||
'playwright': _("编剧"),
|
||||
'actor': _("主演"),
|
||||
|
@ -69,16 +85,20 @@ class MovieForm(forms.ModelForm):
|
|||
'single_episode_length': _("单集片长"),
|
||||
'cover': _("封面"),
|
||||
'brief': _("简介"),
|
||||
'is_series': _("是否是剧集"),
|
||||
'other_info': _("其他信息"),
|
||||
'is_series': _("是否为剧集"),
|
||||
}
|
||||
|
||||
# widgets = {
|
||||
# 'author': forms.TextInput(attrs={'placeholder': _("多个作者使用英文逗号分隔")}),
|
||||
# 'translator': forms.TextInput(attrs={'placeholder': _("多个译者使用英文逗号分隔")}),
|
||||
# 'other_info': KeyValueInput(),
|
||||
# # 'cover': forms.FileInput(),
|
||||
# 'cover': PreviewImageInput(),
|
||||
# }
|
||||
widgets = {
|
||||
'other_title': forms.TextInput(attrs={'placeholder': _("多个别名使用英文逗号分隔")}),
|
||||
'director': forms.TextInput(attrs={'placeholder': _("多个导演使用英文逗号分隔")}),
|
||||
'actor': forms.TextInput(attrs={'placeholder': _("多个主演使用英文逗号分隔")}),
|
||||
'playwright': forms.TextInput(attrs={'placeholder': _("多个编剧使用英文逗号分隔")}),
|
||||
'area': forms.TextInput(attrs={'placeholder': _("多个国家/地区使用英文逗号分隔")}),
|
||||
'language': forms.TextInput(attrs={'placeholder': _("多种语言使用英文逗号分隔")}),
|
||||
'cover': PreviewImageInput(),
|
||||
'is_series': forms.CheckboxInput(attrs={'style': 'width: auto; position: relative; top: 2px'})
|
||||
}
|
||||
|
||||
# def clean_isbn(self):
|
||||
# isbn = self.cleaned_data.get('isbn')
|
||||
|
|
|
@ -4,6 +4,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from django.db import models
|
||||
from django.core.serializers.json import DjangoJSONEncoder
|
||||
from common.models import Resource, Mark, Review, Tag
|
||||
from common.utils import ChoicesDictGenerator
|
||||
from boofilsic.settings import MOVIE_MEDIA_PATH_ROOT, DEFAULT_MOVIE_IMAGE
|
||||
from django.utils import timezone
|
||||
|
||||
|
@ -54,6 +55,9 @@ class MovieGenreEnum(models.TextChoices):
|
|||
TALK_SHOW = 'Talk-Show', _('脱口秀')
|
||||
|
||||
|
||||
MovieGenreTranslator = ChoicesDictGenerator(MovieGenreEnum)
|
||||
|
||||
|
||||
class Movie(Resource):
|
||||
'''
|
||||
Can either be movie or series.
|
||||
|
@ -70,7 +74,7 @@ class Movie(Resource):
|
|||
blank=True,
|
||||
default=list,
|
||||
)
|
||||
imbd_code = models.CharField(
|
||||
imdb_code = models.CharField(
|
||||
blank=True, max_length=10, null=True, unique=True, db_index=True)
|
||||
director = postgres.ArrayField(
|
||||
models.CharField(_("director"), blank=True,
|
||||
|
@ -93,12 +97,17 @@ class Movie(Resource):
|
|||
blank=True,
|
||||
default=list,
|
||||
)
|
||||
genre = models.CharField(
|
||||
_("genre"),
|
||||
genre = postgres.ArrayField(
|
||||
models.CharField(
|
||||
_("genre"),
|
||||
blank=True,
|
||||
default='',
|
||||
choices=MovieGenreEnum.choices,
|
||||
max_length=50
|
||||
),
|
||||
null=True,
|
||||
blank=True,
|
||||
default='',
|
||||
choices=MovieGenreEnum.choices,
|
||||
max_length=50
|
||||
default=list,
|
||||
)
|
||||
showtime = postgres.ArrayField(
|
||||
# HStoreField stores showtime-region pair
|
||||
|
@ -107,7 +116,7 @@ class Movie(Resource):
|
|||
blank=True,
|
||||
default=list,
|
||||
)
|
||||
site = models.URLField(_('site url'), max_length=200)
|
||||
site = models.URLField(_('site url'), blank=True, default='', max_length=200)
|
||||
|
||||
# country or region
|
||||
area = postgres.ArrayField(
|
||||
|
@ -162,6 +171,13 @@ class Movie(Resource):
|
|||
return self.movie_tags
|
||||
|
||||
|
||||
def get_genre_display(self):
|
||||
translated_genre = []
|
||||
for g in self.genre:
|
||||
translated_genre.append(MovieGenreTranslator[g])
|
||||
return translated_genre
|
||||
|
||||
|
||||
class MovieMark(Mark):
|
||||
movie = models.ForeignKey(Movie, on_delete=models.CASCADE, related_name='movie_marks', null=True)
|
||||
class Meta:
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ title }}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ title }}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<!-- <link rel="stylesheet" href="{% static 'lib/css/milligram.css' %}"> -->
|
||||
<!-- <link rel="stylesheet" href="{% static 'css/boofilsic_edit.css' %}"> -->
|
||||
|
@ -27,7 +27,22 @@
|
|||
<div class="single-section-wrapper" id="main">
|
||||
<form class="entity-form" action="{{ submit_url }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
{{ form.media }}
|
||||
{% for field in form %}
|
||||
|
||||
{% if field.id_for_label == 'id_is_series' %}
|
||||
<label for="{{ field.id_for_label }}"
|
||||
style="display: inline-block; position: relative; left: -4px;">{{ field.label }}</label>
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% if field.id_for_label != 'id_id' %}
|
||||
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
|
||||
{% endif %}
|
||||
{{ field }}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<input class="button" type="submit" value="{% trans '提交' %}">
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -10,7 +12,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ title }}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ title }}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/create_update_review.js' %}"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
|
@ -36,16 +38,61 @@
|
|||
</div>
|
||||
<div class="entity-card__info-wrapper entity-card__info-wrapper--horizontal">
|
||||
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">{{ movie.title }}</a></h5>
|
||||
<div>{% if movie.isbn %}{% trans 'ISBN:' %}{{ movie.isbn }}{% endif %}</div>
|
||||
<div>{% if movie.author %}{% trans '作者:' %}
|
||||
{% for author in movie.author %}
|
||||
<span>{{ author }}</span>
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">
|
||||
{% if movie.season %}
|
||||
{{ movie.title }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %} {{ movie.orig_title }} Season
|
||||
{{ movie.season }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
<div>{% if movie.director %}{% trans '导演:' %}
|
||||
{% for director in movie.director %}
|
||||
<span>{{ director }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.genre %}{% trans '类型:' %}
|
||||
{% for genre in movie.get_genre_display %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
<div>{% if movie.actor %}{% trans '主演:' %}
|
||||
{% for actor in movie.actor %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>{{ actor }}</span>
|
||||
{% if forloop.counter <= 5 %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if movie.actor|length > 5 %}
|
||||
<a href="javascript:void(0);" id="actorMore">{% trans '更多' %}</a>
|
||||
<script>
|
||||
$("#actorMore").click(function(e) {
|
||||
$(this).siblings("span:not(:visible)").each(function(e){
|
||||
$(this).removeAttr('style');
|
||||
});
|
||||
$(this).remove();
|
||||
})
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.pub_house %}{% trans '出版社:' %}{{ movie.pub_house }}{% endif %}</div>
|
||||
<div>{%if movie.pub_year %}{% trans '出版时间:' %}{{ movie.pub_year }}{% trans '年' %}{% if movie.pub_month %}{{ movie.pub_month }}{% trans '月' %}{% endif %}{% endif %}</div>
|
||||
|
||||
<div>{% if movie.showtime %}{% trans '上映时间:' %}
|
||||
{% for showtime in movie.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}({{ region }})</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
{% if movie.rating %}
|
||||
{% trans '评分:' %}<span class="entity-card__rating-star rating-star" data-rating-score="{{ movie.rating | floatformat:"0" }}"> </span>
|
||||
<span class="entity-card__rating-score rating-score"> {{ movie.rating }} </span>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -10,7 +12,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 删除电影/剧集' %}</title>
|
||||
<title>{% trans 'NiceDB - 删除电影/剧集' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
@ -39,7 +41,18 @@
|
|||
<div class="entity-card__info-wrapper entity-card__info-wrapper--horizontal">
|
||||
<a href="{% url 'movies:retrieve' movie.id %}">
|
||||
<h5 class="entity-card__title">
|
||||
{{ movie.title }}
|
||||
{% if movie.season %}
|
||||
{{ movie.title }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %} {{ movie.orig_title }} Season
|
||||
{{ movie.season }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</h5>
|
||||
</a>
|
||||
{% if movie.rating %}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 删除评论' %}</title>
|
||||
<title>{% trans 'NiceDB - 删除评论' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="{% static 'lib/css/rating-star.css' %}">
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -10,18 +12,28 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="NiceDB书 - {{ movie.title }}">
|
||||
<meta property="og:type" content="movie">
|
||||
<meta property="og:title" content="NiceDB电影 - {{ movie.title }}">
|
||||
<meta property="og:type" content="video.movie">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:image" content="{{ request.scheme }}://{{ request.get_host }}{{ movie.cover.url }}">
|
||||
{% if movie.author %}
|
||||
<meta property="og:movie:author" content="{% for author in movie.author %}{{ author }}{% if not forloop.last %},{% endif %}{% endfor %}">
|
||||
{% endif %}
|
||||
{% if movie.isbn %}
|
||||
<meta property="og:movie:isbn" content="{{ movie.isbn }}">
|
||||
{% endif %}
|
||||
<meta property="og:site_name" content="NiceDB">
|
||||
<meta property="og:description"content="{{ movie.brief }}">
|
||||
<!--
|
||||
video:actor - profile array - Actors in the movie.
|
||||
video:actor:role - string - The role they played.
|
||||
video:director - profile array - Directors of the movie.
|
||||
video:writer - profile array - Writers of the movie.
|
||||
video:duration - integer >=1 - The movie's length in seconds.
|
||||
video:release_date - datetime - The date the movie was released.
|
||||
video:tag - string array - Tag words associated with this movie.
|
||||
-->
|
||||
|
||||
<title>{% trans 'Nicedb - 电影/剧集详情' %} | {{ movie.title }}</title>
|
||||
{% if movie.is_series %}
|
||||
<title>{% trans 'NiceDB - 剧集详情' %} | {{ movie.title }}</title>
|
||||
{% else %}
|
||||
<title>{% trans 'NiceDB - 电影详情' %} | {{ movie.title }}</title>
|
||||
{% endif %}
|
||||
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/detail.js' %}"></script>
|
||||
|
@ -47,7 +59,18 @@
|
|||
|
||||
<div class="entity-detail__info">
|
||||
<h5 class="entity-detail__title">
|
||||
{{ movie.title }}
|
||||
|
||||
{% if movie.season %}
|
||||
{{ movie.title }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %} {{ movie.orig_title }} Season {{ movie.season }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</h5>
|
||||
|
||||
<div class="entity-detail__fields">
|
||||
|
@ -59,28 +82,80 @@
|
|||
<span> {% trans '评分:暂无评分' %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if movie.isbn %}{% trans 'ISBN:' %}{{ movie.isbn }}{% endif %}</div>
|
||||
<div>{% if movie.author %}{% trans '作者:' %}
|
||||
{% for author in movie.author %}
|
||||
<span>{{ author }}</span>
|
||||
<div>{% if movie.imdb_code %}
|
||||
{% trans 'IMDb:' %}<a href="https://www.imdb.com/title/{{ movie.imdb_code }}/" target="_blank">{{ movie.imdb_code }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>{% if movie.director %}{% trans '导演:' %}
|
||||
{% for director in movie.director %}
|
||||
<span>{{ director }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.pub_house %}{% trans '出版社:' %}{{ movie.pub_house }}{% endif %}</div>
|
||||
<div>{% if movie.subtitle %}{% trans '副标题:' %}{{ movie.subtitle }}{% endif %}</div>
|
||||
<div>{% if movie.translator %}{% trans '译者:' %}
|
||||
{% for translator in movie.translator %}
|
||||
<span>{{ translator }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.orig_title %}{% trans '原作名:' %}{{ movie.orig_title }}{% endif %}</div>
|
||||
<div>{% if movie.language %}{% trans '语言:' %}{{ movie.language }}{% endif %}</div>
|
||||
<div>{%if movie.pub_year %}{% trans '出版时间:' %}{{ movie.pub_year }}{% trans '年' %}{% if movie.pub_month %}{{ movie.pub_month }}{% trans '月' %}{% endif %}{% endif %}</div>
|
||||
<div>{% if movie.playwright %}{% trans '编剧:' %}
|
||||
{% for playwright in movie.playwright %}
|
||||
<span>{{ playwright }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.actor %}{% trans '主演:' %}
|
||||
{% for actor in movie.actor %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;"{% endif %}>{{ actor }}</span>
|
||||
{% if forloop.counter <= 5 %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if movie.actor|length > 5 %}
|
||||
<a href="javascript:void(0);" id="actorMore">{% trans '更多' %}</a>
|
||||
<script>
|
||||
$("#actorMore").click(function(e) {
|
||||
$(this).siblings("span:not(:visible)").each(function(e){
|
||||
$(this).removeAttr('style');
|
||||
});
|
||||
$(this).remove();
|
||||
})
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.genre %}{% trans '类型:' %}
|
||||
{% for genre in movie.get_genre_display %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.area %}{% trans '制片国家/地区:' %}
|
||||
{% for area in movie.area %}
|
||||
<span>{{ area }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.language %}{% trans '语言:' %}
|
||||
{% for language in movie.language %}
|
||||
<span>{{ language }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
</div>
|
||||
<div class="entity-detail__fields">
|
||||
|
||||
<div>{% if movie.binding %}{% trans '装帧:' %}{{ movie.binding }}{% endif %}</div>
|
||||
<div>{% if movie.price %}{% trans '定价:' %}{{ movie.price }}{% endif %}</div>
|
||||
<div>{% if movie.pages %}{% trans '页数:' %}{{ movie.pages }}{% endif %}</div>
|
||||
<div>{% if movie.duration %}{% trans '片长:' %}{{ movie.duration }}{% endif %}</div>
|
||||
<div>{% if movie.season %}{% trans '季数:' %}{{ movie.season }}{% endif %}</div>
|
||||
<div>{% if movie.episodes %}{% trans '集数:' %}{{ movie.episodes }}{% endif %}</div>
|
||||
<div>{% if movie.single_episode_length %}{% trans '单集长度:' %}{{ movie.single_episode_length }}{% endif %}</div>
|
||||
|
||||
<div>{% if movie.showtime %}{% trans '上映时间:' %}
|
||||
{% for showtime in movie.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}({{ region }})</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.other_title %}{% trans '又名:' %}
|
||||
{% for other_title in movie.other_title %}
|
||||
<span>{{ other_title }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.site %}{% trans '网站:' %}
|
||||
<a href="{{ movie.site }}" target="_blank">{{ movie.site }}</a>
|
||||
{% endif %}</div>
|
||||
{% if movie.other_info %}
|
||||
{% for k, v in movie.other_info.items %}
|
||||
<div>
|
||||
|
@ -93,9 +168,13 @@
|
|||
{% if movie.last_editor %}
|
||||
<div>{% trans '最近编辑者:' %}<a href="{% url 'users:home' movie.last_editor.id %}">{{ movie.last_editor | default:"" }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div>
|
||||
<a href="{% url 'movies:update' movie.id %}">{% trans '编辑这部电影/剧集' %}</a>
|
||||
{% if movie.is_series %}
|
||||
<a href="{% url 'movies:update' movie.id %}">{% trans '编辑这部剧集' %}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'movies:update' movie.id %}">{% trans '编辑这部电影' %}</a>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
<a href="{% url 'movies:delete' movie.id %}"> / {% trans '删除' %}</a>
|
||||
{% endif %}
|
||||
|
@ -144,7 +223,12 @@
|
|||
{% endif %}
|
||||
|
||||
<div class="entity-marks">
|
||||
<h5 class="entity-marks__title">{% trans '这部电影/剧集的标记' %}</h5>
|
||||
|
||||
{% if movie.is_series %}
|
||||
<h5 class="entity-marks__title">{% trans '这部剧集的标记' %}</h5>
|
||||
{% else %}
|
||||
<h5 class="entity-marks__title">{% trans '这部电影的标记' %}</h5>
|
||||
{% endif %}
|
||||
{% if mark_list_more %}
|
||||
<a href="{% url 'movies:retrieve_mark_list' movie.id %}" class="entity-marks__more-link">{% trans '更多' %}</a>
|
||||
{% endif %}
|
||||
|
@ -172,7 +256,12 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
<div class="entity-reviews">
|
||||
<h5 class="entity-reviews__title">{% trans '这部电影/剧集的评论' %}</h5>
|
||||
{% if movie.is_series %}
|
||||
<h5 class="entity-reviews__title">{% trans '这部剧集的评论' %}</h5>
|
||||
{% else %}
|
||||
<h5 class="entity-reviews__title">{% trans '这部电影的评论' %}</h5>
|
||||
{% endif %}
|
||||
|
||||
{% if review_list_more %}
|
||||
<a href="{% url 'movies:retrieve_review_list' movie.id %}" class="entity-reviews__more-link">{% trans '更多' %}</a>
|
||||
{% endif %}
|
||||
|
@ -235,7 +324,12 @@
|
|||
</div>
|
||||
{% else %}
|
||||
<div class="action-panel" id="addMarkPanel">
|
||||
<div class="action-panel__label">{% trans '标记这部电影/剧集' %}</div>
|
||||
|
||||
{% if movie.is_series %}
|
||||
<div class="action-panel__label">{% trans '标记这部剧集' %}</div>
|
||||
{% else %}
|
||||
<div class="action-panel__label">{% trans '标记这部电影' %}</div>
|
||||
{% endif %}
|
||||
<div class="action-panel__button-group">
|
||||
<button class="action-panel__button" data-status="{{ status_enum.WISH.value }}" id="wishButton">{% trans '想读' %}</button>
|
||||
<button class="action-panel__button" data-status="{{ status_enum.DO.value }}">{% trans '在读' %}</button>
|
||||
|
@ -294,11 +388,21 @@
|
|||
<div class="mark-modal__head">
|
||||
|
||||
{% if not mark %}
|
||||
|
||||
{% if movie.is_series %}
|
||||
<style>
|
||||
.mark-modal__title::after {
|
||||
content: "{% trans '这部电影/剧集' %}";
|
||||
content: "{% trans '这部剧集' %}";
|
||||
}
|
||||
</style>
|
||||
{% else %}
|
||||
<style>
|
||||
.mark-modal__title::after {
|
||||
content: "{% trans '这部电影' %}";
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
|
||||
<span class="mark-modal__title"></span>
|
||||
{% else %}
|
||||
<span class="mark-modal__title">{% trans '我的标记' %}</span>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -11,7 +13,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ user.username }}{{ list_title }}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ user.username }}{{ list_title }}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
@ -52,7 +54,18 @@
|
|||
<div class="entity-list__entity-text">
|
||||
<div class="entity-list__entity-title">
|
||||
<a href="{% url 'movies:retrieve' mark.movie.id %}" class="entity-list__entity-link">
|
||||
{{ mark.movie.title }}
|
||||
{% if mark.movie.season %}
|
||||
{{ mark.movie.title }} {% trans '第' %}{{ mark.movie.season|apnumber }}{% trans '季' %} {{ mark.movie.orig_title }} Season
|
||||
{{ mark.movie.season }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ mark.movie.year }})
|
||||
</span>
|
||||
{% else %}
|
||||
{{ mark.movie.title }} {{ mark.movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ mark.movie.year }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
{% comment %}
|
||||
|
@ -66,32 +79,36 @@
|
|||
{% endif %} -->
|
||||
{% endcomment %}
|
||||
<span class="entity-list__entity-info entity-list__entity-info--full-length">
|
||||
{% if mark.movie.pub_year %}
|
||||
{{ mark.movie.pub_year }}{% trans '年' %} /
|
||||
{% if mark.movie.pub_month %}
|
||||
{{ mark.movie.pub_month }}{% trans '月' %} /
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if mark.movie.author %}
|
||||
{% trans '作者' %}
|
||||
{% for author in mark.movie.author %}
|
||||
{{ author }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
{% if mark.movie.director %}{% trans '导演' %}
|
||||
{% for director in mark.movie.director %}
|
||||
{{ director }}{% if not forloop.last %} {% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if mark.movie.translator %}
|
||||
{% trans '译者' %}
|
||||
{% for translator in mark.movie.translator %}
|
||||
{{ translator }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if mark.movie.orig_title %}
|
||||
{% trans '原名' %}
|
||||
{{ mark.movie.orig_title }}
|
||||
{% if mark.movie.genre %}{% trans '类型' %}
|
||||
{% for genre in mark.movie.get_genre_display %}
|
||||
{{ genre }}{% if not forloop.last %} {% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if mark.movie.other_title %}{% trans '又名' %}
|
||||
{% for other_title in mark.movie.other_title %}
|
||||
{{ other_title }}{% if not forloop.last %} {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="entity-list__entity-info entity-list__entity-info--full-length">
|
||||
{% if mark.movie.actor %}{% trans '主演' %}
|
||||
{% for actor in mark.movie.actor %}
|
||||
<span {% if forloop.counter > 5 %}style="display: none;" {% endif %}>{{ actor }}</span>
|
||||
{% if forloop.counter <= 5 %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</span>
|
||||
<p class="entity-list__entity-brief">
|
||||
{{ mark.movie.brief | truncate:170 }}
|
||||
</p>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -11,7 +13,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ movie.title }}{% trans '的标记' %}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ movie.title }}{% trans '的标记' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
@ -106,13 +108,40 @@
|
|||
<a href="{% url 'movies:retrieve' movie.id %}"><img src="{{ movie.cover.url }}" alt="" class="entity-card__img"></a>
|
||||
</div>
|
||||
<div class="entity-card__info-wrapper">
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">{{ movie.title }}</a></h5>
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">
|
||||
{% if movie.season %}
|
||||
{{ movie.title }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %} {{ movie.orig_title }} Season
|
||||
{{ movie.season }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
|
||||
{% if movie.isbn %}
|
||||
<div>ISBN: {{ movie.isbn }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div>{% if movie.pub_house %}{% trans '出版社:' %}{{ movie.pub_house }}{% endif %}</div>
|
||||
<div>{% if movie.director %}{% trans '导演:' %}
|
||||
{% for director in movie.director %}
|
||||
<span>{{ director }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.genre %}{% trans '类型:' %}
|
||||
{% for genre in movie.get_genre_display %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
<div>{% if movie.showtime %}{% trans '上映时间:' %}
|
||||
{% for showtime in movie.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}({{ region }})</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
{% if movie.rating %}
|
||||
{% trans '评分: ' %}<span class="entity-card__rating-star rating-star" data-rating-score="{{ movie.rating | floatformat:"0" }}"></span>
|
||||
<span class="entity-card__rating-score rating-score">{{ movie.rating }}</span>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -15,7 +17,7 @@
|
|||
<meta property="og:article:author" content="{{ review.owner.username }}">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:image" content="{{ request.scheme }}://{{ request.get_host }}{% static 'img/logo_square.svg' %}">
|
||||
<title>{% trans 'Nicedb - 评论详情' %}</title>
|
||||
<title>{% trans 'NiceDB - 评论详情' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
@ -85,13 +87,40 @@
|
|||
class="entity-card__img"></a>
|
||||
</div>
|
||||
<div class="entity-card__info-wrapper">
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">{{ movie.title }}</a></h5>
|
||||
|
||||
{% if movie.isbn %}
|
||||
<div>ISBN: {{ movie.isbn }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div>{% if movie.pub_house %}{% trans '出版社:' %}{{ movie.pub_house }}{% endif %}</div>
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">
|
||||
{% if movie.season %}
|
||||
{{ movie.title }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %} {{ movie.orig_title }} Season
|
||||
{{ movie.season }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
|
||||
<div>{% if movie.director %}{% trans '导演:' %}
|
||||
{% for director in movie.director %}
|
||||
<span>{{ director }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.genre %}{% trans '类型:' %}
|
||||
{% for genre in movie.get_genre_display %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
<div>{% if movie.showtime %}{% trans '上映时间:' %}
|
||||
{% for showtime in movie.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}({{ region }})</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
{% if movie.rating %}
|
||||
{% trans '评分: ' %}<span class="entity-card__rating-star rating-star"
|
||||
data-rating-score="{{ movie.rating | floatformat:"0" }}"></span>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -11,7 +13,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - ' %}{{ movie.title }}{% trans '的评论' %}</title>
|
||||
<title>{% trans 'NiceDB - ' %}{{ movie.title }}{% trans '的评论' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'lib/js/rating-star.js' %}"></script>
|
||||
<script src="{% static 'js/rating-star-readonly.js' %}"></script>
|
||||
|
@ -92,13 +94,40 @@
|
|||
class="entity-card__img"></a>
|
||||
</div>
|
||||
<div class="entity-card__info-wrapper">
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">{{ movie.title }}</a></h5>
|
||||
|
||||
{% if movie.isbn %}
|
||||
<div>ISBN: {{ movie.isbn }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div>{% if movie.pub_house %}{% trans '出版社:' %}{{ movie.pub_house }}{% endif %}</div>
|
||||
<h5 class="entity-card__title"><a href="{% url 'movies:retrieve' movie.id %}">
|
||||
{% if movie.season %}
|
||||
{{ movie.title }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %} {{ movie.orig_title }} Season
|
||||
{{ movie.season }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
|
||||
<div>{% if movie.director %}{% trans '导演:' %}
|
||||
{% for director in movie.director %}
|
||||
<span>{{ director }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
<div>{% if movie.genre %}{% trans '类型:' %}
|
||||
{% for genre in movie.get_genre_display %}
|
||||
<span>{{ genre }}</span>{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
|
||||
<div>{% if movie.showtime %}{% trans '上映时间:' %}
|
||||
{% for showtime in movie.showtime %}
|
||||
{% for time, region in showtime.items %}
|
||||
<span>{{ time }}({{ region }})</span>
|
||||
{% endfor %}
|
||||
{% if not forloop.last %} / {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}</div>
|
||||
{% if movie.rating %}
|
||||
{% trans '评分: ' %}<span class="entity-card__rating-star rating-star"
|
||||
data-rating-score="{{ movie.rating | floatformat:"0" }}"></span>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 从豆瓣获取数据' %}</title>
|
||||
<title>{% trans 'NiceDB - 从豆瓣获取数据' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/scrape.js' %}"></script>
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic.css' %}">
|
||||
|
@ -51,7 +51,23 @@
|
|||
<div id="scrapeForm">
|
||||
<form action="{% url 'movies:create' %}" method="POST" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
|
||||
{{ form.media }}
|
||||
|
||||
{% for field in form %}
|
||||
|
||||
{% if field.id_for_label == 'id_is_series' %}
|
||||
<label for="{{ field.id_for_label }}" style="display: inline-block; position: relative; left: -4px;">{{ field.label }}</label>
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% if field.id_for_label != 'id_id' %}
|
||||
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
|
||||
{% endif %}
|
||||
{{ field }}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</form>
|
||||
<a href="{% url 'movies:scrape' %}" class="button add-button submit">{% trans '剽取!' %}</a>
|
||||
</div>
|
||||
|
@ -80,7 +96,10 @@
|
|||
|
||||
</div>
|
||||
<script>
|
||||
|
||||
// mark required
|
||||
$("#content input[required]").each(function () {
|
||||
$(this).prev().prepend("*");
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ def create(request):
|
|||
'movies/create_update.html',
|
||||
{
|
||||
'form': form,
|
||||
'title': _('添加书籍'),
|
||||
'title': _('添加电影/剧集'),
|
||||
'submit_url': reverse("movies:create")
|
||||
}
|
||||
)
|
||||
|
@ -65,7 +65,7 @@ def create(request):
|
|||
'movies/create_update.html',
|
||||
{
|
||||
'form': form,
|
||||
'title': _('添加书籍'),
|
||||
'title': _('添加电影/剧集'),
|
||||
'submit_url': reverse("movies:create")
|
||||
}
|
||||
)
|
||||
|
@ -80,18 +80,20 @@ def update(request, id):
|
|||
if request.method == 'GET':
|
||||
movie = get_object_or_404(Movie, pk=id)
|
||||
form = MovieForm(instance=movie)
|
||||
page_title = _('修改剧集') if movie.is_series else _("修改电影")
|
||||
return render(
|
||||
request,
|
||||
'movies/create_update.html',
|
||||
{
|
||||
'form': form,
|
||||
'title': _('修改书籍'),
|
||||
'title': page_title,
|
||||
'submit_url': reverse("movies:update", args=[movie.id])
|
||||
}
|
||||
)
|
||||
elif request.method == 'POST':
|
||||
movie = get_object_or_404(Movie, pk=id)
|
||||
form = MovieForm(request.POST, request.FILES, instance=movie)
|
||||
page_title = _('修改剧集') if movie.is_series else _("修改电影")
|
||||
if form.is_valid():
|
||||
form.instance.last_editor = request.user
|
||||
form.instance.edited_time = timezone.now()
|
||||
|
@ -102,7 +104,7 @@ def update(request, id):
|
|||
'movies/create_update.html',
|
||||
{
|
||||
'form': form,
|
||||
'title': _('修改书籍'),
|
||||
'title': page_title,
|
||||
'submit_url': reverse("movies:update", args=[movie.id])
|
||||
}
|
||||
)
|
||||
|
@ -132,7 +134,7 @@ def retrieve(request, id):
|
|||
except ObjectDoesNotExist:
|
||||
mark = None
|
||||
if mark:
|
||||
mark_tags = mark.mark_tags.all()
|
||||
mark_tags = mark.moviemark_tags.all()
|
||||
mark.get_status_display = MovieMarkStatusTranslator(mark.status)
|
||||
mark_form = MovieMarkForm(instance=mark, initial={
|
||||
'tags': mark_tags
|
||||
|
@ -239,7 +241,7 @@ def create_update_mark(request):
|
|||
if pk:
|
||||
mark = get_object_or_404(MovieMark, pk=pk)
|
||||
old_rating = mark.rating
|
||||
old_tags = mark.mark_tags.all()
|
||||
old_tags = mark.moviemark_tags.all()
|
||||
# update
|
||||
form = MovieMarkForm(request.POST, instance=mark)
|
||||
else:
|
||||
|
@ -568,10 +570,7 @@ def click_to_scrape(request):
|
|||
form.save()
|
||||
return redirect(reverse('movies:retrieve', args=[form.instance.id]))
|
||||
else:
|
||||
if 'isbn' in form.errors:
|
||||
msg = _("ISBN与现有图书重复")
|
||||
else:
|
||||
msg = _("爬取数据失败😫")
|
||||
msg = _("爬取数据失败😫")
|
||||
return render(request, 'common/error.html', {'msg': msg})
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta property="og:title" content="{% trans 'Nicedb - 登录' %}">
|
||||
<meta property="og:title" content="{% trans 'NiceDB - 登录' %}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:image" content="{{ request.scheme }}://{{ request.get_host }}{% static 'img/logo_square.jpg' %}">
|
||||
<link rel="stylesheet" href="{% static 'lib/css/milligram.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_edit.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_box.css' %}">
|
||||
<title>{% trans 'Nicedb - 登录' %}</title>
|
||||
<title>{% trans 'NiceDB - 登录' %}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="loginBox" class="box">
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 管理举报' %}</title>
|
||||
<title>{% trans 'NiceDB - 管理举报' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/create_update.js' %}"></script>
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic.css' %}">
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<link rel="stylesheet" href="{% static 'lib/css/milligram.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_edit.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic_box.css' %}">
|
||||
<title>{% trans 'Nicedb - 注册' %}</title>
|
||||
<title>{% trans 'NiceDB - 注册' %}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% if is_followers_page %}
|
||||
<title>{% trans 'Nicedb - 被他们关注' %}</title>
|
||||
<title>{% trans 'NiceDB - 被他们关注' %}</title>
|
||||
{% else %}
|
||||
<title>{% trans 'Nicedb - 关注的人' %}</title>
|
||||
<title>{% trans 'NiceDB - 关注的人' %}</title>
|
||||
{% endif %}
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/mastodon.js' %}"></script>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% trans 'Nicedb - 举报用户' %}</title>
|
||||
<title>{% trans 'NiceDB - 举报用户' %}</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.5.0/jquery.min.js"></script>
|
||||
<script src="{% static 'js/create_update.js' %}"></script>
|
||||
<link rel="stylesheet" href="{% static 'css/boofilsic.css' %}">
|
||||
|
|
|
@ -12,6 +12,7 @@ urlpatterns = [
|
|||
path('<int:id>/followers/', followers, name='followers'),
|
||||
path('<int:id>/following/', following, name='following'),
|
||||
path('<int:id>/book/<str:status>/', book_list, name='book_list'),
|
||||
path('<int:id>/movie/<str:status>/', movie_list, name='movie_list'),
|
||||
path('report/', report, name='report'),
|
||||
path('manage_report/', manage_report, name='manage_report'),
|
||||
]
|
||||
|
|
|
@ -12,12 +12,14 @@ from .forms import ReportForm
|
|||
from common.mastodon.auth import *
|
||||
from common.mastodon.api import *
|
||||
from common.mastodon import mastodon_request_included
|
||||
from common.views import BOOKS_PER_SET, ITEMS_PER_PAGE, PAGE_LINK_NUMBER, TAG_NUMBER_ON_LIST
|
||||
from common.views import BOOKS_PER_SET, ITEMS_PER_PAGE, PAGE_LINK_NUMBER, TAG_NUMBER_ON_LIST, MOVIES_PER_SET
|
||||
from common.models import MarkStatusEnum
|
||||
from common.utils import PageLinksGenerator
|
||||
from books.models import *
|
||||
from movies.models import *
|
||||
from boofilsic.settings import MASTODON_DOMAIN_NAME, CLIENT_ID, CLIENT_SECRET
|
||||
from books.forms import BookMarkStatusTranslator
|
||||
from movies.forms import MovieMarkStatusTranslator
|
||||
|
||||
|
||||
# Views
|
||||
|
@ -172,6 +174,17 @@ def home(request, id):
|
|||
|
||||
collect_book_marks = book_marks.filter(status=MarkStatusEnum.COLLECT)
|
||||
collect_books_more = True if collect_book_marks.count() > BOOKS_PER_SET else False
|
||||
|
||||
movie_marks = MovieMark.get_available_user_data(user, relation['following'])
|
||||
do_movie_marks = movie_marks.filter(status=MarkStatusEnum.DO)
|
||||
do_movies_more = True if do_movie_marks.count() > BOOKS_PER_SET else False
|
||||
|
||||
wish_movie_marks = movie_marks.filter(status=MarkStatusEnum.WISH)
|
||||
wish_movies_more = True if wish_movie_marks.count() > BOOKS_PER_SET else False
|
||||
|
||||
collect_movie_marks = movie_marks.filter(status=MarkStatusEnum.COLLECT)
|
||||
collect_movies_more = True if collect_movie_marks.count() > BOOKS_PER_SET else False
|
||||
|
||||
return render(
|
||||
request,
|
||||
'common/home.html',
|
||||
|
@ -183,6 +196,12 @@ def home(request, id):
|
|||
'do_books_more': do_books_more,
|
||||
'wish_books_more': wish_books_more,
|
||||
'collect_books_more': collect_books_more,
|
||||
'do_movie_marks': do_movie_marks[:MOVIES_PER_SET],
|
||||
'wish_movie_marks': wish_movie_marks[:MOVIES_PER_SET],
|
||||
'collect_movie_marks': collect_movie_marks[:MOVIES_PER_SET],
|
||||
'do_movies_more': do_movies_more,
|
||||
'wish_movies_more': wish_movies_more,
|
||||
'collect_movies_more': collect_movies_more,
|
||||
}
|
||||
)
|
||||
else:
|
||||
|
@ -326,6 +345,63 @@ def book_list(request, id, status):
|
|||
)
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
|
||||
@mastodon_request_included
|
||||
@login_required
|
||||
def movie_list(request, id, status):
|
||||
if request.method == 'GET':
|
||||
if not status.upper() in MarkStatusEnum.names:
|
||||
return HttpResponseBadRequest()
|
||||
try:
|
||||
user = User.objects.get(pk=id)
|
||||
except ObjectDoesNotExist:
|
||||
msg = _("😖哎呀这位老师还没有注册书影音呢,快去长毛象喊TA来吧!")
|
||||
sec_msg = _("目前只开放本站用户注册")
|
||||
return render(
|
||||
request,
|
||||
'common/error.html',
|
||||
{
|
||||
'msg': msg,
|
||||
'secondary_msg': sec_msg,
|
||||
}
|
||||
)
|
||||
if not user == request.user:
|
||||
# mastodon request
|
||||
relation = get_relationships([user.mastodon_id], request.session['oauth_token'])[0]
|
||||
if relation['blocked_by']:
|
||||
msg = _("你没有访问TA主页的权限😥")
|
||||
return render(
|
||||
request,
|
||||
'common/error.html',
|
||||
{
|
||||
'msg': msg,
|
||||
}
|
||||
)
|
||||
queryset = MovieMark.get_available_user_data(user, relation['following']).filter(
|
||||
status=MarkStatusEnum[status.upper()]).order_by("-edited_time")
|
||||
else:
|
||||
queryset = MovieMark.objects.filter(
|
||||
owner=user, status=MarkStatusEnum[status.upper()]).order_by("-edited_time")
|
||||
paginator = Paginator(queryset, ITEMS_PER_PAGE)
|
||||
page_number = request.GET.get('page', default=1)
|
||||
marks = paginator.get_page(page_number)
|
||||
for mark in marks:
|
||||
mark.movie.tag_list = mark.movie.get_tags_manager().values('content').annotate(
|
||||
tag_frequency=Count('content')).order_by('-tag_frequency')[:TAG_NUMBER_ON_LIST]
|
||||
marks.pagination = PageLinksGenerator(PAGE_LINK_NUMBER, page_number, paginator.num_pages)
|
||||
list_title = str(MovieMarkStatusTranslator(MarkStatusEnum[status.upper()])) + str(_("的电影和剧集"))
|
||||
return render(
|
||||
request,
|
||||
'movies/list.html',
|
||||
{
|
||||
'marks': marks,
|
||||
'user': user,
|
||||
'list_title' : list_title,
|
||||
}
|
||||
)
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
|
||||
@login_required
|
||||
|
|
Loading…
Add table
Reference in a new issue