[Choeaein] 다중 카테고리의 값에 따른 일정을 달력에 표시하기

silverKi·2023년 7월 31일
0

Choeaein(MyFavor)

목록 보기
3/4
post-thumbnail

project를 build-up하면서 아이돌의 일정을 사용자가 선택한 카테고리와 날짜별로 전처리하는 코드의 개선이 필요하다고 생각했다.

그래서 나는 client가 선택한 카테고리와 날짜 data를 front로부터 배열로 전달 받아 해당 조건에 만족하는 data만 반환하는 API를 생성하였다.


설계 >
1. 사용자가 선택한 카테고리와 날짜 데이터를 배열에 담아 backend에 요청한다.
2. 전달받은 배열에 해당하는 값들의 data만을 반환한다.
frontend-> Post() Request
backend-> Response

예외 >
1. "categories":[ ] 배열에 아무런 값이 없는 경우, 모든 카테고리 버튼이 "활성화" 되었음으로 간주하며, '월'단위 까지 filtering한다.
if len(category_list)==0:

2. 해당 아이돌이 참여하는 스케쥴이 없는 경우 빈 배열을 반환한다.
return Response([], status=HTTP_200_OK)



input: JSON data>

{
 	"categories": ["congrats", "broadcast"],
 	"when":"2023-07-16" or "2023-07"
}

우선 나의 예전 코드에 대해 보면, 각 년,월,일에 따른 메서드를 구성했다.
메서드를 보면 중복되는 부분이 너무 많았다. 년, 월,일 에 대한 부분만 다르고 아이돌 스케쥴 모델에서 조건에 만족한 부분을 필터링하는것 외에는 나머지는 동일하다. 물론 기능에 따라서 class를 구성하고 method를 구성하는것이 좋지만 이 경우에는 좀 더 간결하게 하나의 method로 구성할 수 있을것 같아 변경하기로 하였다.


이전 code

class IdolSchedulesYear(APIView):
    
    def get_object(self, pk):
        
        try:
            return Idol.objects.get(pk=pk)
        except Idol.DoesNotExist:
            return NotFound
    
    def get(self, request, pk, type, year):
        
        idol=self.get_object(pk=pk)
        schedules=idol.idol_schedules.filter(ScheduleType__type=type, when__year=year)
        serializer=DateScheduleSerializer(schedules, many=True)
        return Response(serializer.data, status=HTTP_200_OK) 

class IdolSchedulesMonth(APIView):
    
    def get_object(self, pk):
        
        try:
            return Idol.objects.get(pk=pk)
        except Idol.DoesNotExist:
            return NotFound
    
    def get(self, request, pk, type, year, month):
        
        idol=self.get_object(pk=pk)
        schedules=idol.idol_schedules.filter(ScheduleType__type=type, when__year=year, when__month=month)
        serializer=DateScheduleSerializer(schedules, many=True)
        return Response(serializer.data, status=HTTP_200_OK) 


class IdolScheduelsDay(APIView):
    
    def get_object(self, pk):

        try:
            return Idol.objects.get(pk=pk)
        except Idol.DoesNotExist:
            return NotFound
    
    def get(self, request, pk, type, year, month, day):

        idol=self.get_object(pk=pk)
        schedules=idol.idol_schedules.filter(ScheduleType__type=type, when__year=year, when__month=month, when__day=day)
        
        serializer=DateScheduleSerializer(schedules, many=True)
        return Response(serializer.data, status=HTTP_200_OK) 

filter()부분을 보면 년>월>일>에 대한 depth차이만 있을뿐 나머지 부분은 동일하다.
따라서 중복된 부분을 최소화 하고자 아래의 코드로 변경하여 적용하였다.

변경한 code

class ScheduleDate(APIView):
    def post(self, request, idol_name_en):
           
        all_categories = ["broadcast", "event", "release", "buy", "congrats"]
        category_list = request.data.get("categories", all_categories)
        when= request.data.get("when") # when: DateTimeField
        year, month, day = None, None, None
        
        if when:
            cnt=when.count("-")
            if cnt==2:
                date=datetime.strptime(when, "%Y-%m-%d")
                year=date.year
                month=date.month
                day=date.day
                print("year", year, "month", month)
                print("day", day)
            else:
                date=datetime.strptime(when, "%Y-%m")
                year=date.year
                month=date.month
                print("year", year, "month", month)            
        
        if len(category_list)==0:#아이돌이 참여하는 모든 스케쥴 받아옴
            schedules = Schedule.objects.filter(
                participant__idol_name_en=idol_name_en,
                when__year=year,
                when__month=month
            )
        else:#검색
            schedules = Schedule.objects.filter(
                ScheduleType__type__in=category_list,#사용자가 누른 카테고리가 담긴 리스트
                participant__idol_name_en=idol_name_en,
                when__year=year,#'년'
                when__month=month #'월'        
            )
        if day:#'일'단위 까지 있는 경우 한번 더 필터링 
            schedules = schedules.filter(when__day=day)
        
        if not schedules.exists():#참여하고 있는 스케줄이 없는 경우 
            return Response([], status=HTTP_200_OK)
        
        serializer = ScheduleSerializer(schedules, many=True)

        return Response(serializer.data, status=HTTP_200_OK)

if len(category_list)==0:#아이돌이 참여하는 모든 스케쥴 받아옴
      schedules = Schedule.objects.filter(
           participant__idol_name_en=idol_name_en,
           when__year=year,
           when__month=month
        )

if len(category_list)==0:
만약 client가 카테고리를 아무것도 선택하지 않은 경우,

모든 카테고리 버튼이 활성화 상태로 간주하고, '월'단위 까지만 filtering 한다.

위 경우, 사용자가 달력 page로 들어오게 되면 사용자에게 먼저 해당 아이돌의 월별 일정을 보여줘야 한다고 생각했기 때문이다.

그리고 일자별 일정은 front-end 와 통신하여 frontend에서 일자를 backend에 배열에 담아 요청하면 그에 해당하는 날짜에 관한 일정만 반환하기로 하였다.

profile
아악! 뜨거워!!

2개의 댓글

comment-user-thumbnail
2023년 7월 31일

잘 봤습니다. 좋은 글 감사합니다.

1개의 답글