# blog/views.py from rest_framework import generics, viewsets, permissions, status from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response from django.shortcuts import get_object_or_404 from .models import Post, Comment, Tag from .serializers import PostSerializer, PostListSerializer, CommentSerializer, TagSerializer import logging logger = logging.getLogger(__name__) class TagListView(generics.ListAPIView): """태그 목록 조회""" queryset = Tag.objects.all() serializer_class = TagSerializer permission_classes = [permissions.AllowAny] class PostListView(generics.ListAPIView): """공개 포스트 목록 조회""" queryset = Post.objects.all() serializer_class = PostListSerializer permission_classes = [permissions.AllowAny] def get_queryset(self): queryset = Post.objects.all() tag = self.request.query_params.get('tag') if tag: queryset = queryset.filter(tags__name=tag) return queryset class PostListCreateView(generics.ListCreateAPIView): """인증 사용자용 포스트 목록/생성""" queryset = Post.objects.all() serializer_class = PostSerializer permission_classes = [permissions.IsAuthenticated] def perform_create(self, serializer): user = self.request.user author_id = getattr(user, 'id', '') or getattr(user, 'email', '') author_name = getattr(user, 'username', '') or getattr(user, 'email', '') instance = serializer.save(author_id=str(author_id), author_name=author_name) logger.info(f"Post titled '{instance.title}' has been created by {author_name}.") class PostDetailView(generics.RetrieveUpdateDestroyAPIView): """포스트 상세 조회/수정/삭제""" queryset = Post.objects.all() serializer_class = PostSerializer def get_permissions(self): if self.request.method in ["PUT", "PATCH", "DELETE"]: return [permissions.IsAuthenticated()] return [permissions.AllowAny()] def perform_update(self, serializer): instance = serializer.instance user = self.request.user user_id = str(getattr(user, 'id', '') or getattr(user, 'email', '')) username = getattr(user, 'username', '') or getattr(user, 'email', '') # 작성자 확인 if instance.author_id != user_id and instance.author_name != username: raise PermissionDenied("작성자만 수정할 수 있습니다.") serializer.save() logger.info(f"Post titled '{instance.title}' has been updated by {username}.") def perform_destroy(self, instance): user = self.request.user user_id = str(getattr(user, 'id', '') or getattr(user, 'email', '')) username = getattr(user, 'username', '') or getattr(user, 'email', '') # 작성자 확인 if instance.author_id != user_id and instance.author_name != username: raise PermissionDenied("작성자만 삭제할 수 있습니다.") title = instance.title instance.delete() logger.info(f"Post titled '{title}' has been deleted by {username}.") class CommentViewSet(viewsets.ModelViewSet): """댓글/대댓글 CRUD ViewSet""" serializer_class = CommentSerializer def get_permissions(self): if self.action in ['list', 'retrieve']: return [permissions.AllowAny()] return [permissions.IsAuthenticated()] def get_post(self): """현재 포스트 가져오기""" post_pk = self.kwargs.get('post_pk') return get_object_or_404(Post, pk=post_pk) def get_queryset(self): post_pk = self.kwargs.get('post_pk') if post_pk: # list 액션에서만 최상위 댓글 반환, 나머지는 모든 댓글 접근 가능 if self.action == 'list': return Comment.objects.filter(post_id=post_pk, parent__isnull=True) return Comment.objects.filter(post_id=post_pk) return Comment.objects.none() def perform_create(self, serializer): post = self.get_post() user = self.request.user author_id = str(getattr(user, 'id', '') or getattr(user, 'email', '')) author_name = getattr(user, 'username', '') or getattr(user, 'email', '') # parent 검증 (대댓글인 경우) parent_id = self.request.data.get('parent') parent = None if parent_id: parent = get_object_or_404(Comment, pk=parent_id, post=post) instance = serializer.save( post=post, parent=parent, author_id=author_id, author_name=author_name ) logger.info(f"Comment created on post '{post.title}' by {author_name}.") def perform_update(self, serializer): instance = serializer.instance user = self.request.user user_id = str(getattr(user, 'id', '') or getattr(user, 'email', '')) username = getattr(user, 'username', '') or getattr(user, 'email', '') # 작성자 확인 if instance.author_id != user_id and instance.author_name != username: raise PermissionDenied("작성자만 수정할 수 있습니다.") serializer.save() logger.info(f"Comment {instance.id} updated by {username}.") def perform_destroy(self, instance): user = self.request.user user_id = str(getattr(user, 'id', '') or getattr(user, 'email', '')) username = getattr(user, 'username', '') or getattr(user, 'email', '') # 작성자 확인 if instance.author_id != user_id and instance.author_name != username: raise PermissionDenied("작성자만 삭제할 수 있습니다.") comment_id = instance.id instance.delete() logger.info(f"Comment {comment_id} deleted by {username}.")