Files
msa-django-blog/blog/views.py
icurfer 9f723b403a
Some checks failed
Build And Test / build-and-push (push) Has been cancelled
fix: print 제거, logger 설정 개선, 각 API 동작 로그 추가
2026-01-15 00:47:54 +09:00

175 lines
6.7 KiB
Python

# 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]
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
logger.info(f"Tags list requested. Count: {len(response.data)}")
return response
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
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
tag = request.query_params.get('tag', 'all')
logger.info(f"Posts list requested. Tag: {tag}, Count: {len(response.data)}")
return response
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 retrieve(self, request, *args, **kwargs):
response = super().retrieve(request, *args, **kwargs)
logger.info(f"Post detail requested. ID: {kwargs.get('pk')}, Title: {response.data.get('title')}")
return response
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 list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
post_pk = kwargs.get('post_pk')
logger.info(f"Comments list requested. Post ID: {post_pk}, Count: {len(response.data)}")
return response
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}.")