finish complete movie app
This commit is contained in:
parent
8fd0788047
commit
6efc35697b
27 changed files with 540 additions and 158 deletions
|
@ -70,6 +70,10 @@ class Book(Resource):
|
|||
def get_tags_manager(self):
|
||||
return self.book_tags
|
||||
|
||||
@property
|
||||
def verbose_category_name(self):
|
||||
return _("书籍")
|
||||
|
||||
|
||||
class BookMark(Mark):
|
||||
# maybe this is the better solution, for it has less complex index
|
||||
|
@ -95,4 +99,4 @@ class BookTag(Tag):
|
|||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['content', 'mark'], name="unique_bookmark_tag")
|
||||
]
|
||||
]
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<section id="content" class="container">
|
||||
<div class="grid">
|
||||
<div class="single-section-wrapper" id="main">
|
||||
<a href="{% url 'books:scrape' %}" class="single-section-wrapper__link single-section-wrapper__link--secondary">{% trans '>>> 试试一键剽取~ <<<' %}</a>
|
||||
<form class="entity-form" action="{{ submit_url }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.media }}
|
||||
|
|
|
@ -131,6 +131,12 @@ class TagField(forms.CharField):
|
|||
class MultiSelect(forms.SelectMultiple):
|
||||
template_name = 'widgets/multi_select.html'
|
||||
|
||||
class Media:
|
||||
css = {
|
||||
'all': ('lib/css/multiple-select.min.css',)
|
||||
}
|
||||
js = ('lib/js/multiple-select.min.js',)
|
||||
|
||||
|
||||
class HstoreInput(forms.Widget):
|
||||
template_name = 'widgets/hstore.html'
|
||||
|
@ -154,6 +160,9 @@ class HstoreField(forms.CharField):
|
|||
def to_python(self, value):
|
||||
if not value:
|
||||
return None
|
||||
# already in python types
|
||||
if isinstance(value, list):
|
||||
return value
|
||||
pairs = eval(value)
|
||||
if len(pairs) == 1:
|
||||
pairs = (pairs,)
|
||||
|
|
|
@ -81,21 +81,37 @@ class Resource(models.Model):
|
|||
Since relation between tag and resource is foreign key, and related name has to be unique,
|
||||
this method works like interface.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError("Subclass should implement this method.")
|
||||
|
||||
def get_marks_manager(self):
|
||||
"""
|
||||
Normally this won't be used.
|
||||
There is no ocassion where visitor can simply view all the marks.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError("Subclass should implement this method.")
|
||||
|
||||
def get_revies_manager(self):
|
||||
"""
|
||||
Normally this won't be used.
|
||||
There is no ocassion where visitor can simply view all the reviews.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
raise NotImplementedError("Subclass should implement this method.")
|
||||
|
||||
@classmethod
|
||||
def get_category_mapping_dict(cls):
|
||||
category_mapping_dict = {}
|
||||
for subclass in cls.__subclasses__():
|
||||
category_mapping_dict[subclass.__name__.lower()] = subclass
|
||||
return category_mapping_dict
|
||||
|
||||
@property
|
||||
def category_name(self):
|
||||
return self.__class__.__name__
|
||||
|
||||
@property
|
||||
def verbose_category_name(self):
|
||||
raise NotImplementedError("Subclass should implement this.")
|
||||
|
||||
|
||||
class UserOwnedEntity(models.Model):
|
||||
is_private = models.BooleanField()
|
||||
|
|
|
@ -510,19 +510,39 @@ select::placeholder {
|
|||
|
||||
.navbar .navbar__search-box {
|
||||
margin: 0 12% 0 15px;
|
||||
display: inline-block;
|
||||
display: -webkit-inline-box;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.navbar .navbar__search-box > input[type="search"] {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
margin: 0;
|
||||
height: 32px;
|
||||
background-color: white !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.navbar .navbar__search-box .navbar__search-dropdown {
|
||||
margin: 0;
|
||||
margin-left: -1px;
|
||||
padding: 0;
|
||||
padding-left: 10px;
|
||||
color: #606c76;
|
||||
-webkit-appearance: auto;
|
||||
-moz-appearance: auto;
|
||||
appearance: auto;
|
||||
background-color: white;
|
||||
height: 32px;
|
||||
width: 80px;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.navbar .navbar__dropdown-btn {
|
||||
display: none;
|
||||
padding: 0;
|
||||
|
@ -578,6 +598,11 @@ select::placeholder {
|
|||
height: 26px;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
.navbar .navbar__search-box .navbar__search-dropdown {
|
||||
height: 26px;
|
||||
width: 80px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 991.98px) {
|
||||
|
@ -1128,6 +1153,13 @@ select::placeholder {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.entity-list .entity-list__entity-category {
|
||||
color: #bbb;
|
||||
margin-left: 5px;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.entity-list .entity-list__entity-info {
|
||||
max-width: 73%;
|
||||
white-space: nowrap;
|
||||
|
@ -1635,6 +1667,13 @@ select::placeholder {
|
|||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.add-entity-entries .add-entity-entries__button {
|
||||
line-height: unset;
|
||||
height: unset;
|
||||
padding: 4px 15px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.action-panel {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
@ -1866,6 +1905,7 @@ select::placeholder {
|
|||
}
|
||||
.add-entity-entries .add-entity-entries__button {
|
||||
width: 100%;
|
||||
margin: 5px 0 5px 0;
|
||||
}
|
||||
.aside-section-wrapper:first-child {
|
||||
margin-right: 0 !important;
|
||||
|
@ -1987,6 +2027,16 @@ select::placeholder {
|
|||
overflow: auto;
|
||||
}
|
||||
|
||||
.single-section-wrapper .single-section-wrapper__link--secondary {
|
||||
display: inline-block;
|
||||
color: #ccc;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.single-section-wrapper .single-section-wrapper__link--secondary:hover {
|
||||
color: #00a1cc;
|
||||
}
|
||||
|
||||
.entity-form, .review-form {
|
||||
overflow: auto;
|
||||
}
|
||||
|
|
10
common/static/lib/css/multiple-select.min.css
vendored
Normal file
10
common/static/lib/css/multiple-select.min.css
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* multiple-select - Multiple select is a jQuery plugin to select multiple elements with checkboxes :).
|
||||
*
|
||||
* @version v1.5.2
|
||||
* @homepage http://multiple-select.wenzhixin.net.cn
|
||||
* @author wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
@charset "UTF-8";.ms-offscreen{clip:rect(0 0 0 0)!important;width:1px!important;height:1px!important;border:0!important;margin:0!important;padding:0!important;overflow:hidden!important;position:absolute!important;outline:0!important;left:auto!important;top:auto!important}.ms-parent{display:inline-block;position:relative;vertical-align:middle}.ms-choice{display:block;width:100%;height:26px;padding:0;overflow:hidden;cursor:pointer;border:1px solid #aaa;text-align:left;white-space:nowrap;line-height:26px;color:#444;text-decoration:none;border-radius:4px;background-color:#fff}.ms-choice.disabled{background-color:#f4f4f4;background-image:none;border:1px solid #ddd;cursor:default}.ms-choice>span{position:absolute;top:0;left:0;right:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;padding-left:8px}.ms-choice>span.placeholder{color:#999}.ms-choice>div.icon-close{position:absolute;top:0;right:16px;height:100%;width:16px}.ms-choice>div.icon-close:before{content:'×';color:#888;font-weight:bold;position:absolute;top:50%;margin-top:-14px}.ms-choice>div.icon-close:hover:before{color:#333}.ms-choice>div.icon-caret{position:absolute;width:0;height:0;top:50%;right:8px;margin-top:-2px;border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px}.ms-choice>div.icon-caret.open{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.ms-drop{width:auto;min-width:100%;overflow:hidden;display:none;margin-top:-1px;padding:0;position:absolute;z-index:1000;background:#fff;color:#000;border:1px solid #aaa;border-radius:4px}.ms-drop.bottom{top:100%;box-shadow:0 4px 5px rgba(0,0,0,0.15)}.ms-drop.top{bottom:100%;box-shadow:0 -4px 5px rgba(0,0,0,0.15)}.ms-search{display:inline-block;margin:0;min-height:26px;padding:2px;position:relative;white-space:nowrap;width:100%;z-index:10000;box-sizing:border-box}.ms-search input{width:100%;height:auto!important;min-height:24px;padding:0 5px;margin:0;outline:0;font-family:sans-serif;border:1px solid #aaa;border-radius:5px;box-shadow:none}.ms-drop ul{overflow:auto;margin:0;padding:0}.ms-drop ul>li{list-style:none;display:list-item;background-image:none;position:static;padding:.25rem 8px}.ms-drop ul>li .disabled{font-weight:normal!important;opacity:.35;filter:Alpha(Opacity=35);cursor:default}.ms-drop ul>li.multiple{display:block;float:left}.ms-drop ul>li.group{clear:both}.ms-drop ul>li.multiple label{width:100%;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ms-drop ul>li label{position:relative;padding-left:1.25rem;margin-bottom:0;font-weight:normal;display:block;white-space:nowrap;cursor:pointer}.ms-drop ul>li label.optgroup{font-weight:bold}.ms-drop ul>li.hide-radio{padding:0}.ms-drop ul>li.hide-radio:focus,.ms-drop ul>li.hide-radio:hover{background-color:#f8f9fa}.ms-drop ul>li.hide-radio.selected{color:#fff;background-color:#007bff}.ms-drop ul>li.hide-radio label{margin-bottom:0;padding:5px 8px}.ms-drop ul>li.hide-radio input{display:none}.ms-drop ul>li.option-level-1 label{padding-left:28px}.ms-drop input[type="radio"],.ms-drop input[type="checkbox"]{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.ms-drop .ms-no-results{display:none}
|
10
common/static/lib/js/multiple-select.min.js
vendored
Normal file
10
common/static/lib/js/multiple-select.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -27,6 +27,10 @@ $aside-section-padding-mobile: 24px 25px 10px 25px
|
|||
margin-bottom: 8px
|
||||
|
||||
& &__button
|
||||
line-height: unset;
|
||||
height: unset;
|
||||
padding: 4px 15px;
|
||||
margin: 0 5px;
|
||||
|
||||
.action-panel
|
||||
margin-bottom: 20px
|
||||
|
@ -201,6 +205,7 @@ $aside-section-padding-mobile: 24px 25px 10px 25px
|
|||
display: block !important
|
||||
& &__button
|
||||
width: 100%
|
||||
margin: 5px 0 5px 0;
|
||||
|
||||
.aside-section-wrapper
|
||||
&:first-child
|
||||
|
|
|
@ -47,7 +47,13 @@ $sub-section-title-margin: 8px
|
|||
font-size: 1.2em
|
||||
|
||||
& &__entity-title
|
||||
display: block
|
||||
display: block
|
||||
|
||||
& &__entity-category
|
||||
color: $color-tertiary
|
||||
margin-left: 5px
|
||||
position: relative;
|
||||
top: -1px;
|
||||
|
||||
& &__entity-info
|
||||
max-width: 73%
|
||||
|
|
|
@ -37,14 +37,30 @@
|
|||
|
||||
& &__search-box
|
||||
margin: 0 12% 0 15px
|
||||
display: inline-block
|
||||
display: inline-flex
|
||||
flex: 1
|
||||
$widget-height: 32px
|
||||
& > input[type="search"]
|
||||
border-top-right-radius: 0
|
||||
border-bottom-right-radius: 0
|
||||
margin: 0
|
||||
height: 32px
|
||||
height: $widget-height
|
||||
background-color: white !important
|
||||
width: 100%
|
||||
|
||||
& .navbar__search-dropdown
|
||||
margin: 0
|
||||
margin-left: -1px
|
||||
padding: 0
|
||||
padding-left: 10px
|
||||
color: $color-secondary
|
||||
appearance: auto
|
||||
background-color: white
|
||||
height: $widget-height
|
||||
width: 80px
|
||||
border-top-left-radius: 0
|
||||
border-bottom-left-radius: 0
|
||||
|
||||
& &__dropdown-btn
|
||||
display: none
|
||||
padding: 0
|
||||
|
@ -91,9 +107,14 @@
|
|||
& &__search-box
|
||||
margin: 0
|
||||
width: 46vw
|
||||
$widget-height: 26px
|
||||
& > input[type="search"]
|
||||
height: 26px
|
||||
height: $widget-height
|
||||
padding: 4px 6px
|
||||
& .navbar__search-dropdown
|
||||
height: $widget-height
|
||||
width: 80px
|
||||
padding-left: 5px
|
||||
// Medium devices (tablets, 768px and up)
|
||||
@media (max-width: $medium-devices)
|
||||
pass
|
||||
|
|
|
@ -8,6 +8,12 @@ $single-section-padding-mobile: 32px 28px
|
|||
|
||||
// & input, & select
|
||||
// width: 100%
|
||||
& &__link--secondary
|
||||
display: inline-block
|
||||
color: $color-light
|
||||
margin-bottom: 20px
|
||||
&:hover
|
||||
color: $color-primary
|
||||
|
||||
.entity-form, .review-form
|
||||
overflow: auto
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load humanize %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
|
@ -41,79 +43,181 @@
|
|||
{% endif %}
|
||||
|
||||
<ul class="entity-list__entities">
|
||||
{% for item in items %}
|
||||
|
||||
{% for book in items %}
|
||||
|
||||
<li class="entity-list__entity">
|
||||
<div class="entity-list__entity-img-wrapper">
|
||||
<a href="{% url 'books:retrieve' book.id %}">
|
||||
<img src="{{ book.cover.url }}" alt="" class="entity-list__entity-img">
|
||||
</a>
|
||||
</div>
|
||||
<div class="entity-list__entity-text">
|
||||
|
||||
<div class="entity-list__entity-title">
|
||||
|
||||
<a href="{% url 'books:retrieve' book.id %}" class="entity-list__entity-link">
|
||||
{% if request.GET.q %}
|
||||
{{ book.title | highlight:request.GET.q }}
|
||||
{% else %}
|
||||
{{ book.title }}
|
||||
{% endif %}
|
||||
{% if item.category_name|lower == 'book' %}
|
||||
|
||||
{% with book=item %}
|
||||
<li class="entity-list__entity">
|
||||
<div class="entity-list__entity-img-wrapper">
|
||||
<a href="{% url 'books:retrieve' book.id %}">
|
||||
<img src="{{ book.cover.url }}" alt="" class="entity-list__entity-img">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if book.rating %}
|
||||
<div class="rating-star entity-list__rating-star" data-rating-score="{{ book.rating | floatformat:"0" }}"></div>
|
||||
<span class="entity-list__rating-score rating-score">{{ book.rating }}</span>
|
||||
{% else %}
|
||||
<div class="entity-list__rating entity-list__rating--empty"> {% trans '暂无评分' %}</div>
|
||||
{% endif %}
|
||||
|
||||
<span class="entity-list__entity-info">
|
||||
{% if book.pub_year %}
|
||||
{{ book.pub_year }}{% trans '年' %}
|
||||
{% if book.pub_month %}
|
||||
{{book.pub_month }}{% trans '月' %} /
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if book.author %}
|
||||
{% trans '作者' %}
|
||||
{% for author in book.author %}
|
||||
{{ author }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if book.translator %}
|
||||
{% trans '译者' %}
|
||||
{% for translator in book.translator %}
|
||||
{{ translator }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if book.orig_title %}
|
||||
{% trans '原名' %}
|
||||
{{ book.orig_title }}
|
||||
{% endif %}
|
||||
</span>
|
||||
<p class="entity-list__entity-brief">
|
||||
{{ book.brief }}
|
||||
</p>
|
||||
|
||||
<div class="tag-collection">
|
||||
{% for tag_dict in book.tag_list %}
|
||||
{% for k, v in tag_dict.items %}
|
||||
{% if k == 'content' %}
|
||||
<span class="tag-collection__tag">
|
||||
<a href="{% url 'common:search' %}?tag={{ v }}">{{ v }}</a>
|
||||
</span>
|
||||
<div class="entity-list__entity-text">
|
||||
|
||||
<div class="entity-list__entity-title">
|
||||
|
||||
<a href="{% url 'books:retrieve' book.id %}" class="entity-list__entity-link">
|
||||
{% if request.GET.q %}
|
||||
{{ book.title | highlight:request.GET.q }}
|
||||
{% else %}
|
||||
{{ book.title }}
|
||||
{% endif %}
|
||||
</a>
|
||||
{% if not request.GET.c or request.GET.c != 'movie' and request.GET.c != 'book'%}
|
||||
<span class="entity-list__entity-category">[{{item.verbose_category_name}}]</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if book.rating %}
|
||||
<div class="rating-star entity-list__rating-star" data-rating-score="{{ book.rating | floatformat:"0" }}"></div>
|
||||
<span class="entity-list__rating-score rating-score">{{ book.rating }}</span>
|
||||
{% else %}
|
||||
<div class="entity-list__rating entity-list__rating--empty"> {% trans '暂无评分' %}</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<span class="entity-list__entity-info">
|
||||
{% if book.pub_year %}
|
||||
{{ book.pub_year }}{% trans '年' %}
|
||||
{% if book.pub_month %}
|
||||
{{book.pub_month }}{% trans '月' %} /
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if book.author %}
|
||||
{% trans '作者' %}
|
||||
{% for author in book.author %}
|
||||
{{ author }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if book.translator %}
|
||||
{% trans '译者' %}
|
||||
{% for translator in book.translator %}
|
||||
{{ translator }}{% if not forloop.last %},{% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if book.orig_title %}
|
||||
{% trans '原名' %}
|
||||
{{ book.orig_title }}
|
||||
{% endif %}
|
||||
</span>
|
||||
<p class="entity-list__entity-brief">
|
||||
{{ book.brief }}
|
||||
</p>
|
||||
|
||||
<div class="tag-collection">
|
||||
{% for tag_dict in book.tag_list %}
|
||||
{% for k, v in tag_dict.items %}
|
||||
{% if k == 'content' %}
|
||||
<span class="tag-collection__tag">
|
||||
<a href="{% url 'common:search' %}?tag={{ v }}">{{ v }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</li>
|
||||
{% endwith %}
|
||||
|
||||
{% elif item.category_name|lower == 'movie' %}
|
||||
|
||||
{% with movie=item %}
|
||||
<li class="entity-list__entity">
|
||||
<div class="entity-list__entity-img-wrapper">
|
||||
<a href="{% url 'movies:retrieve' movie.id %}">
|
||||
<img src="{{ movie.cover.url }}" alt="" class="entity-list__entity-img">
|
||||
</a>
|
||||
</div>
|
||||
<div class="entity-list__entity-text">
|
||||
<div class="entity-list__entity-title">
|
||||
<a href="{% url 'movies:retrieve' movie.id %}" class="entity-list__entity-link">
|
||||
{% if movie.season %}
|
||||
|
||||
{% if request.GET.q %}
|
||||
{{ movie.title | highlight:request.GET.q }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %}
|
||||
{{ movie.orig_title | highlight:request.GET.q }} Season {{ movie.season }}
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% else %}
|
||||
{{ movie.title }} {% trans '第' %}{{ movie.season|apnumber }}{% trans '季' %}
|
||||
{{ movie.orig_title }} Season {{ movie.season }}
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
{% if request.GET.q %}
|
||||
{{ movie.title | highlight:request.GET.q }} {{ movie.orig_title | highlight:request.GET.q }}
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
{% if not request.GET.c or request.GET.c != 'movie' and request.GET.c != 'book'%}
|
||||
<span class="entity-list__entity-category">[{{item.verbose_category_name}}]</span>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<span class="entity-list__entity-info entity-list__entity-info--full-length">
|
||||
|
||||
|
||||
{% if movie.director %}{% trans '导演' %}
|
||||
{% for director in movie.director %}
|
||||
{{ director }}{% if not forloop.last %} {% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if movie.genre %}{% trans '类型' %}
|
||||
{% for genre in movie.get_genre_display %}
|
||||
{{ genre }}{% if not forloop.last %} {% endif %}
|
||||
{% endfor %}/
|
||||
{% endif %}
|
||||
|
||||
{% if movie.other_title %}{% trans '又名' %}
|
||||
{% for other_title in 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 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.counter == 5 %} / {% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</span>
|
||||
<p class="entity-list__entity-brief">
|
||||
{{ movie.brief | truncate:170 }}
|
||||
</p>
|
||||
<div class="tag-collection">
|
||||
{% for tag_dict in movie.tag_list %}
|
||||
{% for k, v in tag_dict.items %}
|
||||
{% if k == 'content' %}
|
||||
<span class="tag-collection__tag">
|
||||
<a href="{% url 'common:search' %}?tag={{ v }}">{{ v }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
{% endwith %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
{% empty %}
|
||||
{% trans '无结果' %}
|
||||
{% endfor %}
|
||||
|
@ -153,19 +257,90 @@
|
|||
<div class="add-entity-entries">
|
||||
<div class="add-entity-entries__entry">
|
||||
<div class="add-entity-entries__label">
|
||||
没有想要的结果?
|
||||
{% trans '没有想要的结果?' %}
|
||||
</div>
|
||||
<a href="{% url 'books:create' %}">
|
||||
<button class="add-entity-entries__button">添加一个条目</button>
|
||||
</a>
|
||||
{% if request.GET.c %}
|
||||
|
||||
{% if request.GET.c|lower == 'book' %}
|
||||
|
||||
<a href="{% url 'books:create' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加书' %}</button>
|
||||
</a>
|
||||
|
||||
{% elif request.GET.c|lower == 'movie' %}
|
||||
|
||||
<a href="{% url 'movies:create' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加电影/剧集' %}</button>
|
||||
</a>
|
||||
|
||||
{% else %}
|
||||
<a href="{% url 'books:create' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加书' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'movies:create' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加电影/剧集' %}</button>
|
||||
</a>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<a href="{% url 'books:create' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加书' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'movies:create' %}">
|
||||
<button class="add-entity-entries__button">{% trans '添加电影/剧集' %}</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="add-entity-entries__entry">
|
||||
{% if request.GET.c %}
|
||||
|
||||
{% if request.GET.c|lower == 'book' %}
|
||||
|
||||
<div class="add-entity-entries__label">
|
||||
{% trans '或者(≖ ◡ ≖)✧' %}
|
||||
</div>
|
||||
<a href="{% url 'books:scrape' %}{% if request.GET.q %}?q={{ request.GET.q }}{% endif %}">
|
||||
<button class="add-entity-entries__button">{% trans '从表瓣剽取数据' %}</button>
|
||||
</a>
|
||||
|
||||
{% elif request.GET.c|lower == 'movie' %}
|
||||
|
||||
<div class="add-entity-entries__label">
|
||||
{% trans '或者(≖ ◡ ≖)✧' %}
|
||||
</div>
|
||||
<a href="{% url 'movies:scrape' %}{% if request.GET.q %}?q={{ request.GET.q }}{% endif %}">
|
||||
<button class="add-entity-entries__button">{% trans '从表瓣剽取数据' %}</button>
|
||||
</a>
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="add-entity-entries__label">
|
||||
{% trans '或从表瓣剽取' %}
|
||||
</div>
|
||||
<a href="{% url 'books:scrape' %}{% if request.GET.q %}?q={{ request.GET.q }}{% endif %}">
|
||||
<button class="add-entity-entries__button">{% trans '书' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'movies:scrape' %}{% if request.GET.q %}?q={{ request.GET.q }}{% endif %}">
|
||||
<button class="add-entity-entries__button">{% trans '电影/剧集' %}</button>
|
||||
</a>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
|
||||
<div class="add-entity-entries__label">
|
||||
或者(≖ ◡ ≖)✧
|
||||
{% trans '或从表瓣剽取' %}
|
||||
</div>
|
||||
<a href="{% url 'books:scrape' %}{% if request.GET.q %}?q={{ request.GET.q }}{% endif %}">
|
||||
<button class="add-entity-entries__button">从表瓣剽取数据</button>
|
||||
<button class="add-entity-entries__button">{% trans '书' %}</button>
|
||||
</a>
|
||||
<a href="{% url 'movies:scrape' %}{% if request.GET.q %}?q={{ request.GET.q }}{% endif %}">
|
||||
<button class="add-entity-entries__button">{% trans '电影/剧集' %}</button>
|
||||
</a>
|
||||
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -13,6 +13,11 @@
|
|||
<!-- <input type="search" class="" name="q" id="searchInput" required="true" value="{% for v in request.GET.values %}{{ v }}{% endfor %}" -->
|
||||
<input type="search" class="" name="q" id="searchInput" required="true" value="{% if request.GET.q %}{{ request.GET.q }}{% endif %}"
|
||||
placeholder="搜索书影音">
|
||||
<select class="navbar__search-dropdown" id="searchCategory">
|
||||
<option value="all" {% if request.GET.c and request.GET.c != 'movie' and request.GET.c != 'book' or not request.GET.c %}selected{% endif %}>{% trans '任意' %}</option>
|
||||
<option value="book" {% if request.GET.c and request.GET.c == 'book' %}selected{% endif %}>{% trans '书籍' %}</option>
|
||||
<option value="movie" {% if request.GET.c and request.GET.c == 'movie' %}selected{% endif %}>{% trans '电影' %}</option>
|
||||
</select>
|
||||
</form>
|
||||
<button class="navbar__dropdown-btn">• • •</button>
|
||||
<ul class="navbar__link-list">
|
||||
|
@ -38,8 +43,9 @@
|
|||
$("#searchInput").on('keyup', function (e) {
|
||||
if (e.keyCode === 13) {
|
||||
let q = $(this).val();
|
||||
let c = $("#searchCategory").val();
|
||||
if (q) {
|
||||
location.href = "{% url 'common:search' %}" + "?q=" + q;
|
||||
location.href = "{% url 'common:search' %}" + "?c=" + c + "&q=" + q;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
{% 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,
|
||||
|
|
100
common/views.py
100
common/views.py
|
@ -1,6 +1,9 @@
|
|||
import operator
|
||||
from difflib import SequenceMatcher
|
||||
from django.shortcuts import render
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from books.models import Book
|
||||
from movies.models import Movie
|
||||
from common.models import MarkStatusEnum
|
||||
from common.utils import PageLinksGenerator
|
||||
from users.models import Report, User
|
||||
|
@ -83,28 +86,93 @@ def home(request):
|
|||
@login_required
|
||||
def search(request):
|
||||
if request.method == 'GET':
|
||||
# in the future when more modules are added...
|
||||
# category = request.GET.get("category")
|
||||
q = Q()
|
||||
query_args = []
|
||||
|
||||
# keywords
|
||||
keywords = request.GET.get("q", default='').strip()
|
||||
# category, book/movie/record etc
|
||||
category = request.GET.get("c", default='').strip().lower()
|
||||
|
||||
for keyword in [keywords]:
|
||||
def book_param_handler():
|
||||
q = Q()
|
||||
query_args = []
|
||||
# keywords
|
||||
keywords = request.GET.get("q", default='').strip()
|
||||
|
||||
q = q | Q(title__icontains=keyword)
|
||||
q = q | Q(subtitle__icontains=keyword)
|
||||
q = q | Q(orig_title__icontains=keyword)
|
||||
for keyword in [keywords]:
|
||||
q = q | Q(title__icontains=keyword)
|
||||
q = q | Q(subtitle__icontains=keyword)
|
||||
q = q | Q(orig_title__icontains=keyword)
|
||||
|
||||
# tag
|
||||
tag = request.GET.get("tag", default='')
|
||||
if tag:
|
||||
q = q & Q(book_tags__content__iexact=tag)
|
||||
# tag
|
||||
tag = request.GET.get("tag", default='')
|
||||
if tag:
|
||||
q = q & Q(book_tags__content__iexact=tag)
|
||||
|
||||
query_args.append(q)
|
||||
queryset = Book.objects.filter(*query_args).distinct()
|
||||
query_args.append(q)
|
||||
queryset = Book.objects.filter(*query_args).distinct()
|
||||
|
||||
def calculate_similarity(book):
|
||||
similarity, n = 0, 0
|
||||
for keyword in keywords:
|
||||
similarity += 1/2 * SequenceMatcher(None, keyword, book.title).quick_ratio()
|
||||
+ 1/3 * SequenceMatcher(None, keyword, book.orig_title).quick_ratio()
|
||||
+ 1/6 * SequenceMatcher(None, keyword, book.subtitle).quick_ratio()
|
||||
n += 1
|
||||
book.similarity = similarity / n
|
||||
return book.similarity
|
||||
ordered_queryset = sorted(queryset, key=calculate_similarity, reverse=True)
|
||||
return ordered_queryset
|
||||
|
||||
def movie_param_handler():
|
||||
q = Q()
|
||||
query_args = []
|
||||
# keywords
|
||||
keywords = request.GET.get("q", default='').strip()
|
||||
|
||||
for keyword in [keywords]:
|
||||
q = q | Q(title__icontains=keyword)
|
||||
q = q | Q(other_title__icontains=keyword)
|
||||
q = q | Q(orig_title__icontains=keyword)
|
||||
|
||||
# tag
|
||||
tag = request.GET.get("tag", default='')
|
||||
if tag:
|
||||
q = q & Q(movie_tags__content__iexact=tag)
|
||||
|
||||
query_args.append(q)
|
||||
queryset = Movie.objects.filter(*query_args).distinct()
|
||||
|
||||
def calculate_similarity(movie):
|
||||
similarity, n = 0, 0
|
||||
for keyword in keywords:
|
||||
similarity += 1/2 * SequenceMatcher(None, keyword, movie.title).quick_ratio()
|
||||
+ 1/4 * SequenceMatcher(None, keyword, movie.orig_title).quick_ratio()
|
||||
+ 1/4 * SequenceMatcher(None, keyword, movie.other_title).quick_ratio()
|
||||
n += 1
|
||||
movie.similarity = similarity / n
|
||||
return movie.similarity
|
||||
ordered_queryset = sorted(queryset, key=calculate_similarity, reverse=True)
|
||||
return ordered_queryset
|
||||
|
||||
def all_param_handler():
|
||||
book_queryset = book_param_handler()
|
||||
movie_queryset = movie_param_handler()
|
||||
ordered_queryset = sorted(
|
||||
book_queryset + movie_queryset,
|
||||
key=operator.attrgetter('similarity'),
|
||||
reverse=True
|
||||
)
|
||||
return ordered_queryset
|
||||
|
||||
param_handler = {
|
||||
'book': book_param_handler,
|
||||
'movie': movie_param_handler,
|
||||
'all': all_param_handler,
|
||||
'': all_param_handler
|
||||
}
|
||||
|
||||
try:
|
||||
queryset = param_handler[category]()
|
||||
except KeyError as e:
|
||||
queryset = param_handler['all']()
|
||||
paginator = Paginator(queryset, ITEMS_PER_PAGE)
|
||||
page_number = request.GET.get('page', default=1)
|
||||
items = paginator.get_page(page_number)
|
||||
|
|
|
@ -23,6 +23,7 @@ class MovieForm(forms.ModelForm):
|
|||
|
||||
id = forms.IntegerField(required=False, widget=forms.HiddenInput())
|
||||
genre = forms.MultipleChoiceField(
|
||||
required=False,
|
||||
choices=MovieGenreEnum.choices,
|
||||
widget= MultiSelect,
|
||||
label=_("类型")
|
||||
|
|
|
@ -177,6 +177,13 @@ class Movie(Resource):
|
|||
translated_genre.append(MovieGenreTranslator[g])
|
||||
return translated_genre
|
||||
|
||||
@property
|
||||
def verbose_category_name(self):
|
||||
if self.is_series:
|
||||
return _("剧集")
|
||||
else:
|
||||
return _("电影")
|
||||
|
||||
|
||||
class MovieMark(Mark):
|
||||
movie = models.ForeignKey(Movie, on_delete=models.CASCADE, related_name='movie_marks', null=True)
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
<section id="content" class="container">
|
||||
<div class="grid">
|
||||
<div class="single-section-wrapper" id="main">
|
||||
<a href="{% url 'books:scrape' %}"
|
||||
class="single-section-wrapper__link single-section-wrapper__link--secondary">{% trans '>>> 试试一键剽取~ <<<' %}</a>
|
||||
<form class="entity-form" action="{{ submit_url }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.media }}
|
||||
|
@ -32,7 +34,7 @@
|
|||
|
||||
{% 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>
|
||||
style="display: inline-block; position: relative;">{{ field.label }}</label>
|
||||
{{ field }}
|
||||
{% else %}
|
||||
{% if field.id_for_label != 'id_id' %}
|
||||
|
@ -61,11 +63,29 @@
|
|||
{% endcomment %}
|
||||
|
||||
<script>
|
||||
|
||||
// mark required
|
||||
$("#content input[required]").each(function () {
|
||||
$(this).prev().prepend("*");
|
||||
})
|
||||
|
||||
// `is_seires` checkbox
|
||||
$("#id_season, label[for='id_season']").hide();
|
||||
$("#id_episodes, label[for='id_episodes']").hide();
|
||||
$("#id_single_episode_length, label[for='id_single_episode_length']").hide();
|
||||
$('#id_is_series').change(
|
||||
function () {
|
||||
if ($(this).is(':checked')) {
|
||||
$("#id_season, label[for='id_season']").show();
|
||||
$("#id_episodes, label[for='id_episodes']").show();
|
||||
$("#id_single_episode_length, label[for='id_single_episode_length']").show();
|
||||
} else {
|
||||
$("#id_season, label[for='id_season']").hide();
|
||||
$("#id_episodes, label[for='id_episodes']").hide();
|
||||
$("#id_single_episode_length, label[for='id_single_episode_length']").hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -42,14 +42,12 @@
|
|||
{% 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>
|
||||
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
<div>{% if movie.director %}{% trans '导演:' %}
|
||||
|
|
|
@ -44,14 +44,10 @@
|
|||
{% 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>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
</h5>
|
||||
</a>
|
||||
|
|
|
@ -63,12 +63,12 @@
|
|||
{% 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 }})
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
</span>
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</h5>
|
||||
|
@ -331,9 +331,9 @@
|
|||
<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>
|
||||
<button class="action-panel__button" data-status="{{ status_enum.COLLECT.value }}">{% trans '读过' %}</button>
|
||||
<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>
|
||||
<button class="action-panel__button" data-status="{{ status_enum.COLLECT.value }}">{% trans '看过' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -112,14 +112,10 @@
|
|||
{% 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>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
|
||||
|
|
|
@ -91,14 +91,10 @@
|
|||
{% 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>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
|
||||
|
|
|
@ -98,14 +98,10 @@
|
|||
{% 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>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% else %}
|
||||
{{ movie.title }} {{ movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ movie.year }})
|
||||
</span>
|
||||
{% if movie.year %}({{ movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
</a></h5>
|
||||
|
||||
|
|
|
@ -57,27 +57,14 @@
|
|||
{% 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>
|
||||
{% if mark.movie.year %}({{ mark.movie.year }}){% endif %}
|
||||
|
||||
{% else %}
|
||||
{{ mark.movie.title }} {{ mark.movie.orig_title }}
|
||||
<span class="entity-detail__title entity-detail__title--secondary">
|
||||
({{ mark.movie.year }})
|
||||
</span>
|
||||
{% if mark.movie.year %}({{ mark.movie.year }}){% endif %}
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
{% comment %}
|
||||
<!-- {% if mark.movie.rating %}
|
||||
<div class="rating-star entity-list__rating-star" data-rating-score="{{ mark.movie.rating | floatformat:"0" }}"></div>
|
||||
<span class="entity-list__rating-score rating-score">
|
||||
{{ mark.movie.rating }}
|
||||
</span>
|
||||
{% else %}
|
||||
<div class="entity-list__rating entity-list__rating--empty"> {% trans '暂无评分' %}</div>
|
||||
{% endif %} -->
|
||||
{% endcomment %}
|
||||
<span class="entity-list__entity-info entity-list__entity-info--full-length">
|
||||
|
||||
|
||||
|
@ -104,7 +91,7 @@
|
|||
{% 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 %}
|
||||
{% if not forloop.counter == 5 %} / {% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
|
@ -336,7 +336,7 @@ def book_list(request, id, status):
|
|||
list_title = str(BookMarkStatusTranslator(MarkStatusEnum[status.upper()])) + str(_("的书"))
|
||||
return render(
|
||||
request,
|
||||
'books/list.html',
|
||||
'users/book_list.html',
|
||||
{
|
||||
'marks': marks,
|
||||
'user': user,
|
||||
|
@ -393,7 +393,7 @@ def movie_list(request, id, status):
|
|||
list_title = str(MovieMarkStatusTranslator(MarkStatusEnum[status.upper()])) + str(_("的电影和剧集"))
|
||||
return render(
|
||||
request,
|
||||
'movies/list.html',
|
||||
'users/movie_list.html',
|
||||
{
|
||||
'marks': marks,
|
||||
'user': user,
|
||||
|
|
Loading…
Add table
Reference in a new issue