class BoardDetailActionSerializer(BaseBoardSerializer): from apps.core.serializers.topic import TopicSerializer topics = TopicSerializer( many=True, read_only=True, source='topic_set', )
class ArticleSerializer(BaseArticleSerializer): parent_topic = TopicSerializer(read_only=True, ) parent_board = BoardSerializer(read_only=True, ) from apps.core.serializers.comment import ArticleNestedCommentListActionSerializer comments = ArticleNestedCommentListActionSerializer( many=True, read_only=True, source='comment_set', ) article_update_logs = ArticleUpdateLogSerializer( many=True, read_only=True, source='article_update_log_set', ) comments_count = serializers.ReadOnlyField() nested_comments_count = serializers.ReadOnlyField() is_hidden = serializers.SerializerMethodField(read_only=True, ) why_hidden = serializers.SerializerMethodField(read_only=True, ) title = serializers.SerializerMethodField(read_only=True, ) hidden_title = serializers.SerializerMethodField(read_only=True, ) content = serializers.SerializerMethodField(read_only=True, ) hidden_content = serializers.SerializerMethodField(read_only=True, ) my_vote = serializers.SerializerMethodField(read_only=True, ) my_scrap = serializers.SerializerMethodField(read_only=True, ) my_report = serializers.SerializerMethodField(read_only=True, ) created_by = serializers.SerializerMethodField(read_only=True, ) read_status = serializers.SerializerMethodField(read_only=True, ) article_current_page = serializers.SerializerMethodField(read_only=True, )
class ArticleListActionSerializer(BaseArticleSerializer): parent_topic = TopicSerializer(read_only=True, ) parent_board = BoardSerializer(read_only=True, ) is_hidden = serializers.SerializerMethodField(read_only=True, ) why_hidden = serializers.SerializerMethodField(read_only=True, ) title = serializers.SerializerMethodField(read_only=True, ) hidden_title = serializers.SerializerMethodField(read_only=True, ) created_by = serializers.SerializerMethodField(read_only=True, ) read_status = serializers.SerializerMethodField(read_only=True, )
class SideArticleSerializer(BaseArticleSerializer): class Meta(BaseArticleSerializer.Meta): pass created_by = serializers.SerializerMethodField(read_only=True, ) is_hidden = serializers.SerializerMethodField(read_only=True, ) why_hidden = serializers.SerializerMethodField(read_only=True, ) parent_topic = TopicSerializer(read_only=True, ) title = serializers.SerializerMethodField(read_only=True, ) hidden_title = serializers.SerializerMethodField(read_only=True, )
class ArticleSerializer(BaseArticleSerializer): class Meta(BaseArticleSerializer.Meta): exclude = ( 'migrated_hit_count', 'migrated_positive_vote_count', 'migrated_negative_vote_count', ) @staticmethod def search_articles(queryset, search): return queryset.filter( id__in=ArticleDocument.get_main_search_id_set(search)) @staticmethod def filter_articles(obj, request): from_view = request.query_params.get('from_view') if from_view == '-portal': return Article.objects.exclude(parent_board__slug='portal-notice') elif from_view == 'user': created_by_id = request.query_params.get('created_by', request.user.id) return Article.objects.filter(created_by_id=created_by_id) elif from_view == 'board': parent_board = obj.parent_board return Article.objects.filter(parent_board=parent_board) elif from_view == 'topic': parent_topic = obj.parent_topic return Article.objects.filter(parent_topic=parent_topic) elif from_view == 'scrap': articles = Article.objects.filter( scrap_set__scrapped_by=request.user).order_by( '-scrap_set__created_at') if not articles.filter(id=obj.id).exists(): raise serializers.ValidationError( gettext("This article is not in user's scrap list.")) return articles return Article.objects.all() def get_side_articles(self, obj): request = self.context['request'] from_view = request.query_params.get('from_view') if from_view is None: return {'before': None, 'after': None} if from_view not in [ 'all', '-portal', 'board', 'topic', 'user', 'scrap', 'recent' ]: raise serializers.ValidationError( gettext("Wrong value for parameter 'from_view'.")) if from_view == 'recent': after, before = self.get_side_articles_of_recent_article( obj, request) else: articles = self.filter_articles(obj, request) if request.query_params.get('search_query'): articles = self.search_articles( articles, request.query_params.get('search_query')) articles = articles.exclude(id=obj.id) before = articles.filter(created_at__lte=obj.created_at).first() after = articles.filter(created_at__gte=obj.created_at).last() return { 'before': SideArticleSerializer(before, context=self.context).data if before else None, 'after': SideArticleSerializer(after, context=self.context).data if after else None, } def get_side_articles_of_recent_article(self, obj, request): article_read_log_set = obj.article_read_log_set.all() # 현재 ArticleReadLog curr_read_log_of_obj = article_read_log_set.filter( read_by=request.user, ).order_by('-created_at')[0] # 직전 ArticleReadLog last_read_log_of_obj = article_read_log_set.filter( read_by=request.user, ).order_by('-created_at')[1] # 특정 글의 마지막 ArticleReadLog 를 찾기 위한 Subquery last_read_log_of_article = ArticleReadLog.objects.filter( article=models.OuterRef('pk')).order_by('-created_at') # 특정 글의 마지막 Article created_at 을 last_read_at 으로 annotate 하고, last_read_at 기준으로 정렬 recent_articles = Article.objects.filter( article_read_log_set__read_by=request.user, ).annotate( last_read_at=models.Subquery( queryset=last_read_log_of_article.exclude( id=curr_read_log_of_obj. id, # 무한루프 방지를 위해서 마지막(현재 request) 조회 기록은 제외한다. ).values('created_at')[:1], ), ).order_by( '-last_read_at').distinct() if not recent_articles.filter(id=obj.id).exists(): raise serializers.ValidationError( gettext('This article is never read by user.')) if request.query_params.get('search_query'): recent_articles = self.search_articles( recent_articles, request.query_params.get('search_query')) recent_articles = recent_articles.exclude( id=obj.id, # 자기 자신 제거 ) # 사용자가 현재 읽고 있는 글의 바로 직전 조회 기록보다 먼저 읽은 것 중 첫 번째 before = recent_articles.filter( last_read_at__lte=last_read_log_of_obj.created_at, ).order_by( '-last_read_at').first() # 사용자가 현재 읽고 있는 글의 바로 직전 조회 기록보다 늦게 읽은 것 중 첫 번째 after = recent_articles.filter( last_read_at__gte=last_read_log_of_obj.created_at, ).order_by( 'last_read_at').first() return after, before parent_topic = TopicSerializer(read_only=True, ) parent_board = BoardSerializer(read_only=True, ) from apps.core.serializers.comment import ArticleNestedCommentListActionSerializer comments = ArticleNestedCommentListActionSerializer( many=True, read_only=True, source='comment_set', ) is_hidden = serializers.SerializerMethodField(read_only=True, ) why_hidden = serializers.SerializerMethodField(read_only=True, ) title = serializers.SerializerMethodField(read_only=True, ) hidden_title = serializers.SerializerMethodField(read_only=True, ) content = serializers.SerializerMethodField(read_only=True, ) hidden_content = serializers.SerializerMethodField(read_only=True, ) my_vote = serializers.SerializerMethodField(read_only=True, ) my_scrap = serializers.SerializerMethodField(read_only=True, ) created_by = serializers.SerializerMethodField(read_only=True, ) article_current_page = serializers.SerializerMethodField(read_only=True, ) side_articles = serializers.SerializerMethodField(read_only=True, )