feat: Post 비공개 기능 추가
Some checks failed
Build And Test / build-and-push (push) Has been cancelled

- Post 모델에 is_private 필드 추가
- 비공개 게시글은 작성자만 목록/상세에서 조회 가능
- 공개/비공개 토글 기능 지원

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-25 12:56:05 +09:00
parent c02851e4d3
commit d87d70997b
5 changed files with 59 additions and 7 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.14 on 2026-01-25 03:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('blog', '0006_attachment_batch_id'),
]
operations = [
migrations.AddField(
model_name='post',
name='is_private',
field=models.BooleanField(default=False),
),
]

View File

@ -25,6 +25,7 @@ class Post(models.Model):
updated_at = models.DateTimeField(auto_now=True)
author_id = models.CharField(max_length=150, blank=True, default='')
author_name = models.CharField(max_length=150)
is_private = models.BooleanField(default=False) # 비공개 여부 (True: 작성자만 볼 수 있음)
class Meta:
ordering = ['-created_at']

View File

@ -108,7 +108,8 @@ class PostSerializer(serializers.ModelSerializer):
'author_id', 'author_name',
'created_at', 'updated_at',
'comment_count', 'tags', 'tag_names',
'attachments', 'attachment_ids'
'attachments', 'attachment_ids',
'is_private'
]
read_only_fields = ['author_id', 'author_name', 'created_at', 'updated_at']
@ -178,7 +179,8 @@ class PostListSerializer(serializers.ModelSerializer):
fields = [
'id', 'title',
'author_name', 'created_at', 'updated_at',
'comment_count', 'tags', 'thumbnail'
'comment_count', 'tags', 'thumbnail',
'is_private'
]
def get_comment_count(self, obj):

View File

@ -11,6 +11,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
from django.shortcuts import get_object_or_404
from django.db.models import Q
from .models import Post, Comment, Tag, Attachment
from .serializers import PostSerializer, PostListSerializer, CommentSerializer, TagSerializer, AttachmentSerializer
import logging
@ -66,7 +67,25 @@ class PostListView(generics.ListAPIView):
permission_classes = [permissions.AllowAny]
def get_queryset(self):
queryset = Post.objects.all()
user = self.request.user
if user.is_authenticated:
# 로그인 사용자: 공개 게시글 + 자신의 비공개 게시글
user_id = str(getattr(user, 'id', '') or getattr(user, 'email', ''))
username = getattr(user, 'username', '') or getattr(user, 'email', '')
# 자신의 비공개 게시글 조건 (빈 문자열은 제외)
private_conditions = Q()
if user_id:
private_conditions |= Q(is_private=True, author_id=user_id)
if username:
private_conditions |= Q(is_private=True, author_name=username)
queryset = Post.objects.filter(Q(is_private=False) | private_conditions)
else:
# 비로그인 사용자: 공개 게시글만
queryset = Post.objects.filter(is_private=False)
tag = self.request.query_params.get('tag')
if tag:
queryset = queryset.filter(tags__name=tag)
@ -104,9 +123,21 @@ class PostDetailView(generics.RetrieveUpdateDestroyAPIView):
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
instance = self.get_object()
# 비공개 게시글은 작성자만 조회 가능
if instance.is_private:
user = request.user
if not user.is_authenticated:
raise PermissionDenied("비공개 게시글입니다.")
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 = self.get_serializer(instance)
logger.info(f"Post detail requested. ID: {kwargs.get('pk')}, Title: {serializer.data.get('title')}")
return Response(serializer.data)
def perform_update(self, serializer):
instance = serializer.instance