From ca21d9af0dd090624efe59d8637d1378c586b363 Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 01:13:31 +0900 Subject: [PATCH 1/9] =?UTF-8?q?:white=5Fcheck=5Fmark:Test=20:=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EB=AC=BC=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API=20Test=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 해당 content_id가 존재하는 게시물 상세 조회 시 성공 케이스 - 해당 content_id가 존재하지 않는 게시물 상세 조회 시 실패 케이스 --- posts/tests/views/test_posts_detail_view.py | 60 +++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 posts/tests/views/test_posts_detail_view.py diff --git a/posts/tests/views/test_posts_detail_view.py b/posts/tests/views/test_posts_detail_view.py new file mode 100644 index 0000000..625a6bc --- /dev/null +++ b/posts/tests/views/test_posts_detail_view.py @@ -0,0 +1,60 @@ +import uuid + +from django.contrib.auth import get_user_model +from django.urls import reverse +from django.utils import timezone +from rest_framework import status +from rest_framework.test import APITestCase + +from posts.models import HashTag, Post + +User = get_user_model() + + +class PostListViewTest(APITestCase): + @classmethod + def setUpTestData(cls): + # 테스트 사용자 생성 + cls.user = User.objects.create_user(username="testuser1", password="testpass1", email="test1@email.com") + + # 테스트 해시태그 생성 + cls.hashtag = HashTag.objects.create(name="hashtag1") + + # 테스트 게시물 생성 및 content_id 저장 + cls.content_ids = [] + + # 테스트 게시물 생성 + for i in range(1, 6): + post = Post.objects.create( + content_id=uuid.uuid4(), + user=cls.user, + post_type="facebook", + title=f"test title {i}", + content=f"test content {i}", + view_count=10 * i, + like_count=5 * i, + share_count=2 * i, + created_at=timezone.now(), + updated_at=timezone.now(), + ) + post.hashtag.set([cls.hashtag]) + cls.content_ids.append(str(post.content_id)) + + def setUp(self): + pass + + def test_get_existing_post_content_id(self): + response = self.client.get( + path=reverse("post-detail", kwargs={"content_id": self.content_ids[0]}), + data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, + ) + print(response.data) # 서버의 응답 내용 출력 + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_get_not_existing_post_content_id(self): + non_existing_content_id = "00000000-0000-0000-0000-000000000001" + response = self.client.get( + path=reverse("post-detail", kwargs={"content_id": non_existing_content_id}), + data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, + ) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) From 4a9e32d48b18aa2c3002c5383346f813e3d55c1b Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 01:19:50 +0900 Subject: [PATCH 2/9] =?UTF-8?q?:sparkles:Feat=20:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EB=AC=BC=20=EC=83=81=EC=84=B8=20API=20=EC=9E=91=EC=84=B1=20#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - serializer작성(PostDetailQuerySerializer & PostDetailSerializer) - 게시글 상세조회 관련 view 생성 - /api/posts/에 대한 view 인터페이스 추가 --- posts/serializers.py | 24 ++++++++++++++++++++++++ posts/urls.py | 3 ++- posts/views.py | 26 ++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/posts/serializers.py b/posts/serializers.py index 3a36501..97ffc09 100644 --- a/posts/serializers.py +++ b/posts/serializers.py @@ -74,3 +74,27 @@ class PostQuerySerializer(serializers.Serializer): help_text="created_at, updated_at, view_count, like_count, share_count를 기준으로 오름차순/내림차순으로 정렬하여 조회합니다. (default: created_at)", ) hashtag = serializers.CharField(required=False, help_text="조회할 해시태그입니다. (default: 본인계정)") + + +class PostDetailSerializer(serializers.ModelSerializer): + hashtag = HashTagSerializer(many=True, read_only=True) + + class Meta: + model = Post + fields = [ + "content_id", + "post_type", + "title", + "content", + "view_count", + "like_count", + "share_count", + "created_at", + "updated_at", + "hashtag", + "user", + ] + + +class PostDetailQuerySerializer(serializers.Serializer): + content_id = serializers.UUIDField() diff --git a/posts/urls.py b/posts/urls.py index 714b6ee..302e8ab 100644 --- a/posts/urls.py +++ b/posts/urls.py @@ -1,8 +1,9 @@ from django.urls import path -from posts.views import PostListView, StatisticsListView +from posts.views import PostDetailView, PostListView, StatisticsListView urlpatterns = [ path("statistics/", StatisticsListView.as_view(), name="statistics"), path("", PostListView.as_view(), name="list"), + path("/", PostDetailView.as_view(), name="post-detail"), ] diff --git a/posts/views.py b/posts/views.py index a9e3a6b..77140d9 100644 --- a/posts/views.py +++ b/posts/views.py @@ -3,6 +3,7 @@ from django.db.models import Count, Q, Sum from django.db.models.functions import TruncDay, TruncHour from django.db.models.query import QuerySet +from django.shortcuts import get_object_or_404 from drf_yasg.utils import swagger_auto_schema from rest_framework import status from rest_framework.pagination import LimitOffsetPagination @@ -18,6 +19,8 @@ from posts.models import Post from posts.paginations import PaginationHandlerMixin from posts.serializers import ( + PostDetailQuerySerializer, + PostDetailSerializer, PostListSerializer, PostQuerySerializer, StatisticsListSerializer, @@ -210,3 +213,26 @@ def get_ordering(self, posts: QuerySet[Post], ordering: str) -> QuerySet[Post]: return posts.order_by(ordering) else: raise InvalidParameterException(f"ordering 값 {ordering}를 잘못 선택하셨습니다.") + + +class PostDetailView(APIView): + # @TODO: IsAuthenticated로 변경 @simseulnyang + permission_classes = [AllowAny] + + @swagger_auto_schema( + operation_summary="content_id에 해당하는 게시글 상세 조회", + query_serializer=PostDetailQuerySerializer, + responses={ + status.HTTP_200_OK: PostDetailSerializer, + }, + ) + def get(self, request: Request, content_id: str) -> Response: + post = get_object_or_404(Post, content_id=content_id) + + # 게시글 조회수 증가 + post.view_count += 1 + post.save() + + serializer = PostDetailSerializer(post) + + return Response(serializer.data, status=status.HTTP_200_OK) From 3578fb97e5655b173bbf2bc0dc29802d57f5f967 Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 01:13:31 +0900 Subject: [PATCH 3/9] =?UTF-8?q?:white=5Fcheck=5Fmark:Test=20:=20=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=EB=AC=BC=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API=20Test=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 해당 content_id가 존재하는 게시물 상세 조회 시 성공 케이스 - 해당 content_id가 존재하지 않는 게시물 상세 조회 시 실패 케이스 --- posts/tests/views/test_posts_detail_view.py | 60 +++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 posts/tests/views/test_posts_detail_view.py diff --git a/posts/tests/views/test_posts_detail_view.py b/posts/tests/views/test_posts_detail_view.py new file mode 100644 index 0000000..625a6bc --- /dev/null +++ b/posts/tests/views/test_posts_detail_view.py @@ -0,0 +1,60 @@ +import uuid + +from django.contrib.auth import get_user_model +from django.urls import reverse +from django.utils import timezone +from rest_framework import status +from rest_framework.test import APITestCase + +from posts.models import HashTag, Post + +User = get_user_model() + + +class PostListViewTest(APITestCase): + @classmethod + def setUpTestData(cls): + # 테스트 사용자 생성 + cls.user = User.objects.create_user(username="testuser1", password="testpass1", email="test1@email.com") + + # 테스트 해시태그 생성 + cls.hashtag = HashTag.objects.create(name="hashtag1") + + # 테스트 게시물 생성 및 content_id 저장 + cls.content_ids = [] + + # 테스트 게시물 생성 + for i in range(1, 6): + post = Post.objects.create( + content_id=uuid.uuid4(), + user=cls.user, + post_type="facebook", + title=f"test title {i}", + content=f"test content {i}", + view_count=10 * i, + like_count=5 * i, + share_count=2 * i, + created_at=timezone.now(), + updated_at=timezone.now(), + ) + post.hashtag.set([cls.hashtag]) + cls.content_ids.append(str(post.content_id)) + + def setUp(self): + pass + + def test_get_existing_post_content_id(self): + response = self.client.get( + path=reverse("post-detail", kwargs={"content_id": self.content_ids[0]}), + data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, + ) + print(response.data) # 서버의 응답 내용 출력 + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_get_not_existing_post_content_id(self): + non_existing_content_id = "00000000-0000-0000-0000-000000000001" + response = self.client.get( + path=reverse("post-detail", kwargs={"content_id": non_existing_content_id}), + data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, + ) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) From d646a63030890eda93e17f7d1ac397e4431c80cc Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 01:19:50 +0900 Subject: [PATCH 4/9] =?UTF-8?q?:sparkles:Feat=20:=20=EA=B2=8C=EC=8B=9C?= =?UTF-8?q?=EB=AC=BC=20=EC=83=81=EC=84=B8=20API=20=EC=9E=91=EC=84=B1=20#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - serializer작성(PostDetailQuerySerializer & PostDetailSerializer) - 게시글 상세조회 관련 view 생성 - /api/posts/에 대한 view 인터페이스 추가 --- posts/serializers.py | 24 ++++++++++++++++++++++++ posts/urls.py | 3 ++- posts/views.py | 26 ++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/posts/serializers.py b/posts/serializers.py index 3a36501..97ffc09 100644 --- a/posts/serializers.py +++ b/posts/serializers.py @@ -74,3 +74,27 @@ class PostQuerySerializer(serializers.Serializer): help_text="created_at, updated_at, view_count, like_count, share_count를 기준으로 오름차순/내림차순으로 정렬하여 조회합니다. (default: created_at)", ) hashtag = serializers.CharField(required=False, help_text="조회할 해시태그입니다. (default: 본인계정)") + + +class PostDetailSerializer(serializers.ModelSerializer): + hashtag = HashTagSerializer(many=True, read_only=True) + + class Meta: + model = Post + fields = [ + "content_id", + "post_type", + "title", + "content", + "view_count", + "like_count", + "share_count", + "created_at", + "updated_at", + "hashtag", + "user", + ] + + +class PostDetailQuerySerializer(serializers.Serializer): + content_id = serializers.UUIDField() diff --git a/posts/urls.py b/posts/urls.py index 714b6ee..302e8ab 100644 --- a/posts/urls.py +++ b/posts/urls.py @@ -1,8 +1,9 @@ from django.urls import path -from posts.views import PostListView, StatisticsListView +from posts.views import PostDetailView, PostListView, StatisticsListView urlpatterns = [ path("statistics/", StatisticsListView.as_view(), name="statistics"), path("", PostListView.as_view(), name="list"), + path("/", PostDetailView.as_view(), name="post-detail"), ] diff --git a/posts/views.py b/posts/views.py index a9e3a6b..77140d9 100644 --- a/posts/views.py +++ b/posts/views.py @@ -3,6 +3,7 @@ from django.db.models import Count, Q, Sum from django.db.models.functions import TruncDay, TruncHour from django.db.models.query import QuerySet +from django.shortcuts import get_object_or_404 from drf_yasg.utils import swagger_auto_schema from rest_framework import status from rest_framework.pagination import LimitOffsetPagination @@ -18,6 +19,8 @@ from posts.models import Post from posts.paginations import PaginationHandlerMixin from posts.serializers import ( + PostDetailQuerySerializer, + PostDetailSerializer, PostListSerializer, PostQuerySerializer, StatisticsListSerializer, @@ -210,3 +213,26 @@ def get_ordering(self, posts: QuerySet[Post], ordering: str) -> QuerySet[Post]: return posts.order_by(ordering) else: raise InvalidParameterException(f"ordering 값 {ordering}를 잘못 선택하셨습니다.") + + +class PostDetailView(APIView): + # @TODO: IsAuthenticated로 변경 @simseulnyang + permission_classes = [AllowAny] + + @swagger_auto_schema( + operation_summary="content_id에 해당하는 게시글 상세 조회", + query_serializer=PostDetailQuerySerializer, + responses={ + status.HTTP_200_OK: PostDetailSerializer, + }, + ) + def get(self, request: Request, content_id: str) -> Response: + post = get_object_or_404(Post, content_id=content_id) + + # 게시글 조회수 증가 + post.view_count += 1 + post.save() + + serializer = PostDetailSerializer(post) + + return Response(serializer.data, status=status.HTTP_200_OK) From c7ca08f4d9f5c171df82908e838c26280d379bcf Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 16:30:24 +0900 Subject: [PATCH 5/9] =?UTF-8?q?:recycle:Refactor=20:=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=9D=BC=EB=B6=80=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - test_posts_detail_view의 print문 삭제 - PostDetail의 qeury_serializer 삭제 - serializer에 작성한 PostDetailQuerySerializer 삭제 --- posts/serializers.py | 4 ---- posts/tests/views/test_posts_detail_view.py | 1 - posts/views.py | 2 -- 3 files changed, 7 deletions(-) diff --git a/posts/serializers.py b/posts/serializers.py index 97ffc09..0dfd789 100644 --- a/posts/serializers.py +++ b/posts/serializers.py @@ -94,7 +94,3 @@ class Meta: "hashtag", "user", ] - - -class PostDetailQuerySerializer(serializers.Serializer): - content_id = serializers.UUIDField() diff --git a/posts/tests/views/test_posts_detail_view.py b/posts/tests/views/test_posts_detail_view.py index 625a6bc..d913a37 100644 --- a/posts/tests/views/test_posts_detail_view.py +++ b/posts/tests/views/test_posts_detail_view.py @@ -48,7 +48,6 @@ def test_get_existing_post_content_id(self): path=reverse("post-detail", kwargs={"content_id": self.content_ids[0]}), data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, ) - print(response.data) # 서버의 응답 내용 출력 self.assertEqual(response.status_code, status.HTTP_200_OK) def test_get_not_existing_post_content_id(self): diff --git a/posts/views.py b/posts/views.py index 77140d9..2a76b1d 100644 --- a/posts/views.py +++ b/posts/views.py @@ -19,7 +19,6 @@ from posts.models import Post from posts.paginations import PaginationHandlerMixin from posts.serializers import ( - PostDetailQuerySerializer, PostDetailSerializer, PostListSerializer, PostQuerySerializer, @@ -221,7 +220,6 @@ class PostDetailView(APIView): @swagger_auto_schema( operation_summary="content_id에 해당하는 게시글 상세 조회", - query_serializer=PostDetailQuerySerializer, responses={ status.HTTP_200_OK: PostDetailSerializer, }, From 4da1e75394ac04e9d6aef1cf9f720cc4f3c5ed80 Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 17:11:40 +0900 Subject: [PATCH 6/9] =?UTF-8?q?:sparkles:Feat=20:=20Django=20signal=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=8B=9C=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=20?= =?UTF-8?q?=EC=A6=9D=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - signals.py 생성 및 조회수 증가 로직 구현 - apps.py 업데이트하여 signal 활성화 - views.py PostDetail 클래스에 작성한 조회수 증가 코드 삭제 - 조회수 증가와 관련한 testcode 작성 --- posts/apps.py | 3 +++ posts/signals.py | 10 +++++++++ posts/tests/views/test_posts_detail_view.py | 25 +++++++++++++++++++++ posts/views.py | 5 ----- 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 posts/signals.py diff --git a/posts/apps.py b/posts/apps.py index 81782a2..7648802 100644 --- a/posts/apps.py +++ b/posts/apps.py @@ -4,3 +4,6 @@ class PostsConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "posts" + + def ready(self): + pass diff --git a/posts/signals.py b/posts/signals.py new file mode 100644 index 0000000..c1115f0 --- /dev/null +++ b/posts/signals.py @@ -0,0 +1,10 @@ +from django.db.models.signals import pre_save +from django.dispatch import receiver + +from posts.models import Post + + +@receiver(pre_save, sender=Post) +def increment_view_count(sender, instance, **kwargs): + # 게시글을 조회할 때 조회수 증가 + instance.view_count += 1 diff --git a/posts/tests/views/test_posts_detail_view.py b/posts/tests/views/test_posts_detail_view.py index d913a37..9f1fefd 100644 --- a/posts/tests/views/test_posts_detail_view.py +++ b/posts/tests/views/test_posts_detail_view.py @@ -1,6 +1,7 @@ import uuid from django.contrib.auth import get_user_model +from django.db import transaction from django.urls import reverse from django.utils import timezone from rest_framework import status @@ -57,3 +58,27 @@ def test_get_not_existing_post_content_id(self): data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, ) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_increment_view_count(self): + content_id = self.content_ids[0] + + # 현재 조회수 가져오기 + # 초기값 - 1 (조회와 동시에 count가 됨) + post = Post.objects.get(content_id=content_id) + initial_view_count = post.view_count - 1 + + # 게시물 조회 + with transaction.atomic(): + response = self.client.get( + path=reverse("post-detail", kwargs={"content_id": content_id}), + data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, + ) + + # 조회수 업데이트 확인 + post.refresh_from_db() + updated_view_count = post.view_count + + print("initial_view_count", initial_view_count) + + self.assertEqual(updated_view_count, initial_view_count + 1) + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/posts/views.py b/posts/views.py index 2a76b1d..29a446c 100644 --- a/posts/views.py +++ b/posts/views.py @@ -226,11 +226,6 @@ class PostDetailView(APIView): ) def get(self, request: Request, content_id: str) -> Response: post = get_object_or_404(Post, content_id=content_id) - - # 게시글 조회수 증가 - post.view_count += 1 - post.save() - serializer = PostDetailSerializer(post) return Response(serializer.data, status=status.HTTP_200_OK) From eff854c93b8f4cc7ba10d5016ea68944c7dcd190 Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 17:11:40 +0900 Subject: [PATCH 7/9] =?UTF-8?q?:sparkles:Feat=20:=20Django=20signal=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=8B=9C=20=EC=A1=B0=ED=9A=8C=20=EC=88=98=20?= =?UTF-8?q?=EC=A6=9D=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - signals.py 생성 및 조회수 증가 로직 구현 - apps.py 업데이트하여 signal 활성화 - views.py PostDetail 클래스에 작성한 조회수 증가 코드 삭제 - 조회수 증가와 관련한 testcode 작성 --- posts/apps.py | 3 +++ posts/signals.py | 10 +++++++++ posts/tests/views/test_posts_detail_view.py | 25 +++++++++++++++++++++ posts/views.py | 5 ----- 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 posts/signals.py diff --git a/posts/apps.py b/posts/apps.py index 81782a2..7648802 100644 --- a/posts/apps.py +++ b/posts/apps.py @@ -4,3 +4,6 @@ class PostsConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "posts" + + def ready(self): + pass diff --git a/posts/signals.py b/posts/signals.py new file mode 100644 index 0000000..c1115f0 --- /dev/null +++ b/posts/signals.py @@ -0,0 +1,10 @@ +from django.db.models.signals import pre_save +from django.dispatch import receiver + +from posts.models import Post + + +@receiver(pre_save, sender=Post) +def increment_view_count(sender, instance, **kwargs): + # 게시글을 조회할 때 조회수 증가 + instance.view_count += 1 diff --git a/posts/tests/views/test_posts_detail_view.py b/posts/tests/views/test_posts_detail_view.py index d913a37..9f1fefd 100644 --- a/posts/tests/views/test_posts_detail_view.py +++ b/posts/tests/views/test_posts_detail_view.py @@ -1,6 +1,7 @@ import uuid from django.contrib.auth import get_user_model +from django.db import transaction from django.urls import reverse from django.utils import timezone from rest_framework import status @@ -57,3 +58,27 @@ def test_get_not_existing_post_content_id(self): data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, ) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_increment_view_count(self): + content_id = self.content_ids[0] + + # 현재 조회수 가져오기 + # 초기값 - 1 (조회와 동시에 count가 됨) + post = Post.objects.get(content_id=content_id) + initial_view_count = post.view_count - 1 + + # 게시물 조회 + with transaction.atomic(): + response = self.client.get( + path=reverse("post-detail", kwargs={"content_id": content_id}), + data={"type": "all", "hashtag": self.hashtag.id, "ordering": "created_at", "search": ""}, + ) + + # 조회수 업데이트 확인 + post.refresh_from_db() + updated_view_count = post.view_count + + print("initial_view_count", initial_view_count) + + self.assertEqual(updated_view_count, initial_view_count + 1) + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/posts/views.py b/posts/views.py index 2a76b1d..29a446c 100644 --- a/posts/views.py +++ b/posts/views.py @@ -226,11 +226,6 @@ class PostDetailView(APIView): ) def get(self, request: Request, content_id: str) -> Response: post = get_object_or_404(Post, content_id=content_id) - - # 게시글 조회수 증가 - post.view_count += 1 - post.save() - serializer = PostDetailSerializer(post) return Response(serializer.data, status=status.HTTP_200_OK) From d5c055c0fddef242ec5217bc69dfeec211b9a03a Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 17:31:15 +0900 Subject: [PATCH 8/9] =?UTF-8?q?:recycle:Refactor=20:=20signals=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=EC=9D=84=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20imp?= =?UTF-8?q?ort=EB=AC=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - signals 모듈을 가져오는 import 문을 추가했습니다. - 이 import 문은 signals이 제대로 로드되고 실행되도록 하는 데 필요합니다. --- posts/apps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/apps.py b/posts/apps.py index 7648802..cd95585 100644 --- a/posts/apps.py +++ b/posts/apps.py @@ -6,4 +6,4 @@ class PostsConfig(AppConfig): name = "posts" def ready(self): - pass + import posts.signals # noqa From ba89c3acf3f942c13f5368dc47b84f5df4a53adf Mon Sep 17 00:00:00 2001 From: simseulnyang Date: Mon, 30 Oct 2023 17:41:15 +0900 Subject: [PATCH 9/9] =?UTF-8?q?:hammer:Chore=20:=20testcode=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=AA=85=20=EB=B3=80=EA=B2=BD(PostListViewTe?= =?UTF-8?q?st=20->=20PostDetailViewTest)=20#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 게시물 상세 조회 관련 테스트 코드를 위한 클래스명이어서 관련 명으로 교체 --- posts/tests/views/test_posts_detail_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/tests/views/test_posts_detail_view.py b/posts/tests/views/test_posts_detail_view.py index 9f1fefd..e39302b 100644 --- a/posts/tests/views/test_posts_detail_view.py +++ b/posts/tests/views/test_posts_detail_view.py @@ -12,7 +12,7 @@ User = get_user_model() -class PostListViewTest(APITestCase): +class PostDetailViewTest(APITestCase): @classmethod def setUpTestData(cls): # 테스트 사용자 생성