diff --git a/common/models.py b/common/models.py index fe317393..5098ea1f 100644 --- a/common/models.py +++ b/common/models.py @@ -4,7 +4,7 @@ from markdown import markdown from django.utils.translation import gettext_lazy as _ from django.db import models, IntegrityError from django.core.serializers.json import DjangoJSONEncoder -from django.db.models import Q +from django.db.models import Q, Count from markdownx.models import MarkdownxField from users.models import User from mastodon.api import get_relationships, get_cross_site_id @@ -197,8 +197,10 @@ class UserOwnedEntity(models.Model): :param is_following: if the current user is following the owner """ user_owned_entities = cls.objects.filter(owner=owner) - if not is_following: - user_owned_entities = user_owned_entities.exclude(visibility__gt=0) + if is_following: + user_owned_entities = user_owned_entities.exclude(visibility__ne=2) + else: + user_owned_entities = user_owned_entities.filter(visibility=0) return user_owned_entities @@ -255,5 +257,22 @@ class Tag(models.Model): def __str__(self): return self.content + @property + def edited_time(self): + return self.mark.edited_time + + @classmethod + def find_by_user(cls, tag, owner, is_following): + user_owned_entities = cls.objects.filter(content=tag, mark__owner=owner) + if is_following: + user_owned_entities = user_owned_entities.exclude(mark__visibility__ne=2) + else: + user_owned_entities = user_owned_entities.filter(mark__visibility=0) + return user_owned_entities + + @classmethod + def all_by_user(cls, owner): + return cls.objects.filter(mark__owner=owner).values('content').annotate(total=Count('content')).order_by('-total') + class Meta: abstract = True diff --git a/users/templates/users/home.html b/users/templates/users/home.html index b4b7d6bb..18ba2e88 100644 --- a/users/templates/users/home.html +++ b/users/templates/users/home.html @@ -703,6 +703,53 @@ +
+
+ {% trans '常用标签' %} +
+
+ {% if book_tags %} +
{% trans '书籍' %}
+ {% for v in book_tags %} + + {{ v }} + + {% endfor %} +
+ {% endif %} + + {% if movie_tags %} +
{% trans '电影和剧集' %}
+ {% for v in movie_tags %} + + {{ v }} + + {% endfor %} +
+ {% endif %} + + {% if music_tags %} +
{% trans '音乐' %}
+ {% for v in music_tags %} + + {{ v }} + + {% endfor %} +
+ {% endif %} + + {% if game_tags %} +
{% trans '游戏' %}
+ {% for v in game_tags %} + + {{ v }} + + {% endfor %} +
+ {% endif %} +
+
+ diff --git a/users/views.py b/users/views.py index ad3b7a35..b6597b82 100644 --- a/users/views.py +++ b/users/views.py @@ -354,6 +354,11 @@ def home(request, id): **music_marks_count, **game_marks_count, + 'book_tags': list(map(lambda t: t['content'], BookTag.all_by_user(user)))[:10] if user == request.user else [], + 'movie_tags': list(map(lambda t: t['content'], MovieTag.all_by_user(user)))[:10] if user == request.user else [], + 'music_tags': list(map(lambda t: t['content'], AlbumTag.all_by_user(user)))[:10] if user == request.user else [], + 'game_tags': list(map(lambda t: t['content'], GameTag.all_by_user(user)))[:10] if user == request.user else [], + 'book_reviews': book_reviews.order_by("-edited_time")[:BOOKS_PER_SET], 'movie_reviews': movie_reviews.order_by("-edited_time")[:MOVIES_PER_SET], 'music_reviews': music_reviews[:MUSIC_PER_SET], @@ -533,7 +538,7 @@ def following(request, id): @login_required def book_list(request, id, status): if request.method == 'GET': - if status.upper() not in MarkStatusEnum.names and status != 'reviewed': + if status.upper() not in MarkStatusEnum.names and status not in ['reviewed', 'tagged']: return HttpResponseBadRequest() if isinstance(id, str): @@ -558,6 +563,7 @@ def book_list(request, id, status): 'secondary_msg': sec_msg, } ) + tag = request.GET.get('t', default='') if user != request.user: # mastodon request relation = get_relationship(request.user, user, request.session['oauth_token'])[0] @@ -572,6 +578,8 @@ def book_list(request, id, status): ) if status == 'reviewed': queryset = BookReview.get_available_by_user(user, relation['following']).order_by("-edited_time") + elif status == 'tagged': + queryset = BookTag.find_by_user(tag, user, relation['following']).order_by("-mark__edited_time") else: queryset = BookMark.get_available_by_user(user, relation['following']).filter( status=MarkStatusEnum[status.upper()]).order_by("-edited_time") @@ -580,6 +588,8 @@ def book_list(request, id, status): else: if status == 'reviewed': queryset = BookReview.objects.filter(owner=user).order_by("-edited_time") + elif status == 'tagged': + queryset = BookTag.objects.filter(content=tag, mark__owner=user).order_by("-mark__edited_time") else: queryset = BookMark.objects.filter( owner=user, status=MarkStatusEnum[status.upper()]).order_by("-edited_time") @@ -590,7 +600,12 @@ def book_list(request, id, status): mark.book.tag_list = mark.book.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(BookMarkStatusTranslator(MarkStatusEnum[status.upper()]) if status != 'reviewed' else _("评论过"))) + str(_("的书")) + if status == 'reviewed': + list_title = str(_("评论过的书")) + elif status == 'tagged': + list_title = str(_(f"标记为「{tag}」的书")) + else: + list_title = str(BookMarkStatusTranslator(MarkStatusEnum[status.upper()])) + str(_("的书")) return render( request, 'users/book_list.html', @@ -609,7 +624,7 @@ def book_list(request, id, status): @login_required def movie_list(request, id, status): if request.method == 'GET': - if status.upper() not in MarkStatusEnum.names and status != 'reviewed': + if status.upper() not in MarkStatusEnum.names and status not in ['reviewed', 'tagged']: return HttpResponseBadRequest() if isinstance(id, str): @@ -634,6 +649,7 @@ def movie_list(request, id, status): 'secondary_msg': sec_msg, } ) + tag = request.GET.get('t', default='') if user != request.user: # mastodon request relation = get_relationship(request.user, user, request.session['oauth_token'])[0] @@ -650,12 +666,16 @@ def movie_list(request, id, status): user, request.user.mastodon_site, request.session['oauth_token']) if status == 'reviewed': queryset = MovieReview.get_available_by_user(user, relation['following']).order_by("-edited_time") + elif status == 'tagged': + queryset = MovieTag.find_by_user(tag, user, relation['following']).order_by("-mark__edited_time") else: queryset = MovieMark.get_available_by_user(user, relation['following']).filter( status=MarkStatusEnum[status.upper()]).order_by("-edited_time") else: if status == 'reviewed': queryset = MovieReview.objects.filter(owner=user).order_by("-edited_time") + elif status == 'tagged': + queryset = MovieTag.objects.filter(content=tag, mark__owner=user).order_by("-mark__edited_time") else: queryset = MovieMark.objects.filter(owner=user, status=MarkStatusEnum[status.upper()]).order_by("-edited_time") paginator = Paginator(queryset, ITEMS_PER_PAGE) @@ -665,7 +685,13 @@ def movie_list(request, id, status): 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()])) if status != 'reviewed' else _("评论过")) + str(_("的电影和剧集")) + if status == 'reviewed': + list_title = str(_("评论过的电影和剧集")) + elif status == 'tagged': + list_title = str(_(f"标记为「{tag}」的电影和剧集")) + else: + list_title = str(MovieMarkStatusTranslator(MarkStatusEnum[status.upper()])) + str(_("的电影和剧集")) + return render( request, 'users/movie_list.html', @@ -684,7 +710,7 @@ def movie_list(request, id, status): @login_required def game_list(request, id, status): if request.method == 'GET': - if status.upper() not in MarkStatusEnum.names and status != 'reviewed': + if status.upper() not in MarkStatusEnum.names and status not in ['reviewed', 'tagged']: return HttpResponseBadRequest() if isinstance(id, str): @@ -709,6 +735,7 @@ def game_list(request, id, status): 'secondary_msg': sec_msg, } ) + tag = request.GET.get('t', default='') if user != request.user: # mastodon request relation = get_relationship(request.user, user, request.session['oauth_token'])[0] @@ -725,12 +752,16 @@ def game_list(request, id, status): user, request.user.mastodon_site, request.session['oauth_token']) if status == 'reviewed': queryset = GameReview.get_available_by_user(user, relation['following']).order_by("-edited_time") + elif status == 'tagged': + queryset = GameTag.find_by_user(tag, user, relation['following']).order_by("-mark__edited_time") else: queryset = GameMark.get_available_by_user(user, relation['following']).filter( status=MarkStatusEnum[status.upper()]).order_by("-edited_time") else: if status == 'reviewed': queryset = GameReview.objects.filter(owner=user).order_by("-edited_time") + elif status == 'tagged': + queryset = GameTag.objects.filter(content=tag, mark__owner=user).order_by("-mark__edited_time") else: queryset = GameMark.objects.filter( owner=user, status=MarkStatusEnum[status.upper()]).order_by("-edited_time") @@ -741,7 +772,12 @@ def game_list(request, id, status): mark.game.tag_list = mark.game.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(GameMarkStatusTranslator(MarkStatusEnum[status.upper()])) if status != 'reviewed' else _("评论过")) + str(_("的游戏")) + if status == 'reviewed': + list_title = str(_("评论过的游戏")) + elif status == 'tagged': + list_title = str(_(f"标记为「{tag}」的游戏")) + else: + list_title = str(GameMarkStatusTranslator(MarkStatusEnum[status.upper()])) + str(_("的游戏")) return render( request, 'users/game_list.html', @@ -760,7 +796,7 @@ def game_list(request, id, status): @login_required def music_list(request, id, status): if request.method == 'GET': - if status.upper() not in MarkStatusEnum.names and status != 'reviewed': + if status.upper() not in MarkStatusEnum.names and status not in ['reviewed', 'tagged']: return HttpResponseBadRequest() if isinstance(id, str): @@ -785,6 +821,7 @@ def music_list(request, id, status): 'secondary_msg': sec_msg, } ) + tag = request.GET.get('t', default='') if not user == request.user: # mastodon request relation = get_relationship(request.user, user, request.session['oauth_token'])[0] @@ -800,6 +837,8 @@ def music_list(request, id, status): if status == 'reviewed': queryset = list(AlbumReview.get_available_by_user(user, relation['following']).order_by("-edited_time")) + \ list(SongReview.get_available_by_user(user, relation['following']).order_by("-edited_time")) + elif status == 'tagged': + queryset = list(AlbumTag.find_by_user(tag, user, relation['following']).order_by("-mark__edited_time")) else: queryset = list(AlbumMark.get_available_by_user(user, relation['following']).filter( status=MarkStatusEnum[status.upper()])) \ @@ -812,6 +851,8 @@ def music_list(request, id, status): if status == 'reviewed': queryset = list(AlbumReview.objects.filter(owner=user).order_by("-edited_time")) + \ list(SongReview.objects.filter(owner=user).order_by("-edited_time")) + elif status == 'tagged': + queryset = list(AlbumTag.objects.filter(content=tag, mark__owner=user).order_by("-mark__edited_time")) else: queryset = list(AlbumMark.objects.filter(owner=user, status=MarkStatusEnum[status.upper()])) \ + list(SongMark.objects.filter(owner=user, status=MarkStatusEnum[status.upper()])) @@ -820,7 +861,7 @@ def music_list(request, id, status): page_number = request.GET.get('page', default=1) marks = paginator.get_page(page_number) for mark in marks: - if mark.__class__ == AlbumMark or mark.__class__ == AlbumReview: + if mark.__class__ in [AlbumMark, AlbumReview, AlbumTag]: mark.music = mark.album mark.music.tag_list = mark.album.get_tags_manager().values('content').annotate( tag_frequency=Count('content')).order_by('-tag_frequency')[:TAG_NUMBER_ON_LIST] @@ -830,7 +871,12 @@ def music_list(request, id, status): 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(MusicMarkStatusTranslator(MarkStatusEnum[status.upper()]) if status != 'reviewed' else _("评论过"))) + str(_("的音乐")) + if status == 'reviewed': + list_title = str(_("评论过的音乐")) + elif status == 'tagged': + list_title = str(_(f"标记为「{tag}」的音乐")) + else: + list_title = str(MusicMarkStatusTranslator(MarkStatusEnum[status.upper()])) + str(_("的音乐")) return render( request, 'users/music_list.html',