지난 시간에는 인스타그램 팔로우 기능을 구현하였습니다. 이번에는 게시물 및 댓글 삭제, 수정기능을 구현하겠습니다. 마찬가지로 로그인 데코레이터를 사용해서 로그인된 권한있는 유저만이 기능을 사용할 수 있도록 하겠습니다.
게시물 및 댓글 삭제, 수정 기능은 게시물과 관련되어 있으므로 posting
앱에서 작성합니다.
# posting/models.py
from django.db import models
from user.models import User
class Posting(models.Model):
content = models.CharField(max_length=2000, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) --> 추가
user = models.ForeignKey('user.User', on_delete=models.CASCADE)
class Meta:
db_table = 'postings'
Posting
클래스에 게시물의 생성시간을 기록하는 created_at
만 있었는데, 수정시간을 기록하는 updated_at
필드를 추가하였습니다.
게시물과 댓글은 삭제를 하는 로직이 같으므로, 게시물을 기준으로 설명하도록 하겠습니다.
게시물을 삭제한다면 보통 특정 게시물의 id를 받아 삭제합니다. 전체를 한꺼번에 삭제하지는 않죠. 따라서PostingDetailView
클래스를 만들어 상세 정보를 관리할 수 있도록 합니다.
class PostingDetailView(View):
보통 게시물은 작성한 본인만 삭제할 수 있으므로, 로그인 토큰을 통해 받은 유저 정보(user
)와 해당 포스팅의 작성자(posting.user
)가 동일한지 확인합니다.
@login_decorator
def delete(self, request, posting_id):
user = request.user
if not Posting.objects.filter(id=posting_id).exists():
return JsonResponse({'message':'POSTING_DOES_NOT_EXIST'}, status=404)
posting = Posting.objects.get(id=posting_id)
if user != posting.user:
return JsonResponse({'message':'INVALID_USER'}, status=401)
수정 또한 상세 정보를 다루는 것이므로 PostingDetailView
에서 작성합니다.
수정할 때는 patch
나 put
을 사용해도 되지만 저는 post
를 사용하도록 하겠습니다.
class PostingDetailView(View):
(...생략)
@login_decorator
def post(self, request, posting_id):
삭제 기능과 마찬가지로 로그인한 유저와 작성자가 같은지 확인해야 합니다.
저는 수정 기능을 딕셔너리 get 메소드를 이용하여 구현합니다.
이 방식의 장점은 이 포스팅에 자세히 설명해두었습니다.
posting.content = data.get('content', posting.content)
posting.save()
# posting/views.py
(...생략)
class PostingDetailView(View):
@login_decorator
def delete(self, request, posting_id):
user = request.user
if not Posting.objects.filter(id=posting_id).exists():
return JsonResponse({'message':'POSTING_DOES_NOT_EXIST'}, status=404)
posting = Posting.objects.get(id=posting_id)
if user != posting.user:
return JsonResponse({'message':'INVALID_USER'}, status=401)
Posting.objects.filter(id=posting.id).delete()
return JsonResponse({'message': 'SUCCESS'}, status=200)
@login_decorator
def post(self, request, posting_id):
try:
data = json.loads(request.body)
user = request.user
if not Posting.objects.filter(id=posting_id).exists():
return JsonResponse({'message': 'POSTING_DOES_NOT_EXIST'}, status=404)
posting = Posting.objects.get(id=posting_id)
if user != posting.user:
return JsonResponse({'message':'INVALID_USER'}, status=401)
posting.content = data.get('content', posting.content)
posting.save()
return JsonResponse({'message': 'SUCCESS'}, status=201)
except JSONDecodeError:
return JsonResponse({'message':'JSON_DECODE_ERROR'}, status=400)
(...생략)
class CommentDetailView(View):
@login_decorator
def delete(self, request, comment_id):
user = request.user
if not Comment.objects.filter(id=comment_id).exists():
return JsonResponse({'message':'COMMENT_DOES_NOT_EXIST'}, status=404)
comment = Comment.objects.get(id=comment_id)
if user != comment.user:
return JsonResponse({'message':'INVALID_USER'}, status=401)
Comment.objects.filter(id=comment.id).delete()
return JsonResponse({'message': 'SUCCESS'}, status=200)
# posting/urls.py
from django.urls import path
from .views import (
PostingView,
PostingSearchView,
PostingDetailView, --> 추가
CommentView,
CommentSearchView,
CommentDetailView, --> 추가
LikeView,
)
urlpatterns = [
path('', PostingView.as_view()),
path('/search/<int:user_id>', PostingSearchView.as_view()),
path('/<int:posting_id>', PostingDetailView.as_view()), --> 추가
path('/comment', CommentView.as_view()),
path('/comment/search/<int:posting_id>', CommentSearchView.as_view()),
path('/comment/<int:comment_id>', CommentDetailView.as_view()), --> 추가
path('/like', LikeView.as_view()),
]