From dea03d90991797619523b0ea09a8451a64febc39 Mon Sep 17 00:00:00 2001 From: sm4640 Date: Sat, 12 Apr 2025 01:53:23 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Feat:=20[#22]=20=EC=A1=B0=ED=9A=8C,?= =?UTF-8?q?=EC=83=9D=EC=84=B1,=EC=82=AD=EC=A0=9C,=EB=8C=80=ED=91=9C/?= =?UTF-8?q?=EB=B0=B0=ED=8F=AC=20=EA=B4=80=EB=A6=AC,=EC=83=81=ED=83=9C?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- portfolios/views.py | 106 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/portfolios/views.py b/portfolios/views.py index 91ea44a..a7a2e08 100644 --- a/portfolios/views.py +++ b/portfolios/views.py @@ -1,3 +1,105 @@ -from django.shortcuts import render +from django.shortcuts import get_object_or_404 -# Create your views here. +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status + +from .models import * + +from django_filters.rest_framework import DjangoFilterBackend +from rest_framework.filters import OrderingFilter +from rest_framework.generics import ListAPIView +from .serializers import PortfolioListViewSerializer, PortfolioCreateSerializer +from .paginations import PortfolioPagination +from .filters import PortfolioFilter +from .services import PortfolioStateChangeService, PortfolioBeforeRelCheckService + +from django.db import transaction + + +class PortfolioListView(ListAPIView): + queryset = Portfolio.objects.filter(is_published=True).order_by('-created_at') + serializer_class = PortfolioListViewSerializer + pagination_class = PortfolioPagination + filterset_class = PortfolioFilter + filter_backends = [DjangoFilterBackend, OrderingFilter] + ordering_fields = ['view_count', 'like_count', 'scrap_count', 'created_at'] # 허용할 필드 추천순 제외 + ordering = ['-created_at'] # 기본 정렬은 최신순 + +class PortfolioCreateAPIView(APIView): + @transaction.atomic + def post(self, request): + data = request.data.copy() + data['owner'] = request.user.id + serializer = PortfolioCreateSerializer(data=data) + if serializer.is_valid(): + serializer.save() + return Response({"message": "create portfolio success"}, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + +class PortfolioDeleteAPIView(APIView): + @transaction.atomic + def delete(self, request, pk): + user = request.user + portfolio = get_object_or_404(Portfolio, id=pk) + if user != portfolio.owner: + return Response({"message": "Not owner"}, status=status.HTTP_403_FORBIDDEN) + portfolio.delete() + return Response({"message": "delete success"}, status=status.HTTP_200_OK) + +class PortfolioSetRepresentAPIView(APIView): + @transaction.atomic + def patch(self, request, pk): + user = request.user + portfolio = get_object_or_404(Portfolio, id=pk) + if user != portfolio.owner: + return Response({"message": "Not owner"}, status=status.HTTP_403_FORBIDDEN) + if before_represent := Portfolio.objects.filter(owner=user, is_represent=True).first(): + before_represent.is_represent = False + portfolio.is_represent = True + return Response({"message": "change represent success"}, status=status.HTTP_200_OK) + + +class PortfolioSetPublishAPIView(APIView): + @transaction.atomic + def patch(self, request, pk): + user = request.user + portfolio = get_object_or_404(Portfolio, id=pk) + if user != portfolio.owner: + return Response({"message": "Not owner"}, status=status.HTTP_403_FORBIDDEN) + portfolio.is_published = True + portfolio.save() + return Response({"message": "publish success"}, status=status.HTTP_200_OK) + +class PortfolioChangeState(APIView): + @transaction.atomic + def patch(self, request, pk): + portfolio = get_object_or_404(Portfolio, pk=pk) + user = request.user + action_type = request.query_params.get('type') + if PortfolioBeforeRelCheckService.check_user_portfolio_rel(action_type, portfolio, user): + return Response({"message": "already done"}, status=status.HTTP_400_BAD_REQUEST) + return self._handle_action(action_type, portfolio, user, add=True) + + @transaction.atomic + def delete(self, request, pk): + portfolio = get_object_or_404(Portfolio, pk=pk) + user = request.user + action_type = request.query_params.get('type') + if not PortfolioBeforeRelCheckService.check_user_portfolio_rel(action_type, portfolio, user): + return Response({"message": "never done before"}, status=status.HTTP_400_BAD_REQUEST) + return self._handle_action(action_type, portfolio, user, add=False) + + def _handle_action(self, action_type, portfolio, user, add=True): + if not action_type: + return Response({'message': 'Missing action type'}, status=status.HTTP_400_BAD_REQUEST) + + try: + PortfolioStateChangeService.change_user_portfolio_rel(action_type, portfolio, user, add) + PortfolioStateChangeService.change_count_portfolio_state(action_type, portfolio, add) + except ValueError as e: + return Response({'message': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + return Response({ + 'message': f'{action_type} {"added" if add else "removed"}' + }, status=status.HTTP_200_OK) \ No newline at end of file