- [ISSUE]decorator를 이용한 중복작업 전처리2023년 05월 05일
- 조별하
- 작성자
- 2023.05.05.:02
[22.11.26]
🍃 중복되며 각 함수의 사전에 처리되는 작업 decorator
📌 SiteBulkAPIView - 벌크 즐겨찾기, 삭제
class SiteBulkAPIView(APIView): """ 벌크 항목 즐겨찾기, 삭제 api """ def get_list(self): pk_ids: list = self.request.data.get('pk_ids') return get_list_or_404(Site, id__in=pk_ids) def validate_ids(self): pk_ids: list = self.request.data.get('pk_ids') for id in pk_ids: get_object_or_404(Site,id=id) return self.get_list() def put(self, request): """ Site 벌크 즐겨찾기 추가 """ sites = self.validate_ids() try: with transaction.atomic(): '''트랜젝션 시작''' for site in sites: site.favorite = self.request.data.get('favorite') site.save() except: raise Response({'msg':'Updated failed'}, status=status.HTTP_400_BAD_REQUEST) return Response({'msg':'Updated successfully'}, status=status.HTTP_200_OK) def delete(self, request): """ Site 벌크 삭제 """ sites = self.get_list() for site in sites: site.delete() return Response({'msg': 'Deleted successfully'}, status=status.HTTP_200_OK)
📌 SiteTagsAPIView - 벌크 태그
class SiteTagsAPIView(APIView): """ 벌크 항목 태그 api """ def get_list(self): pk_ids: list = self.request.data.get('pk_ids') return get_list_or_404(Site, id__in=pk_ids) def validate_ids(self): pk_ids: list = self.request.data.get('pk_ids') for id in pk_ids: get_object_or_404(Site,id=id) return self.get_list() def post(self, request, **kwards): """ Site 태그 추가 """ sites = validate_ids() tags = self.request.data.get('tags') with transaction.atomic(): '''트랜젝션 시작''' created_tags = [Tag.objects.create(name=tag) for tag in tags] [tag.site.add(site.id) for tag in created_tags for site in sites] return Response({'msg':'Updated successfully'}, status=status.HTTP_200_OK)
🍃 코드 작성 시 문제점
✔️ 벌크 즐겨찾기, 삭제 Class를 코드를 작성한 후, 벌크 태그 Class 코드를 작성하는데 bulk작업이다 보니 데이터를 조회하고 검증하는 작업이 두 Class에서 반복적으로 사용이 됐다.
def get_list(self): pk_ids: list = self.request.data.get('pk_ids') return get_list_or_404(Site, id__in=pk_ids) def validate_ids(self): pk_ids: list = self.request.data.get('pk_ids') for id in pk_ids: get_object_or_404(Site,id=id) return self.get_list()
📌 해결방법
✔️ 반복되는 데이터 조회와 검증하는 작업을 decorator로 분리를 시키고 각 class의 api함수에서는 반복되는 코드를 줄이는 작업을 진행해보자
📌 decorator 사용
def bulk_decorator(func): @wraps(func) def exec_func(self, request) -> func: pk_ids: list = self.request.data.get('pk_ids') sites = validate_ids(pk_ids) return func(self, request, sites=sites) def get_list(pk_ids: list) -> Site: return get_list_or_404(Site, id__in=pk_ids) def validate_ids(pk_ids: list) -> Site: for id in pk_ids: get_object_or_404(Site,id=id) return get_list(pk_ids) return exec_func
✔️ bulk_decorator함수
- 데코레이터 실행 함수 exec_func를 실행할 수 있게 return으로 exec_func를 반환
- 각 Class에서 작성하던 중복되던 함수 get_list와 validate_ids함수를 bulk_decorator내부 함수로 작성
- exec_func내부에 pk_ids로 전달받은 pk(id) 배열 값을 validate_ids()함수의 매개변수로 호출하여 sites 변수에 담아 실행함수 return 값으로 전달받은 함수의 키워드 가변인자 값으로 전달해 주게 변경
✔️ @bulk_decorator 사용
class SiteTagsAPIView(APIView): """ 벌크 항목 태그 api """ **@bulk_decorator** def post(self, request, **kwards): """ Site 태그 추가 """ sites = **kwards['sites']** tags = self.request.data.get('tags') with transaction.atomic(): '''트랜젝션 시작''' created_tags = [Tag.objects.get_or_create(name=tag)[0] for tag in tags] [tag.site.add(site.id) for tag in created_tags for site in sites] return Response({'msg':'Add tag successfully'}, status=status.HTTP_200_OK)
class SiteTagsAPIView(APIView): """ 벌크 항목 태그 api """ @bulk_decorator def post(self, request, **kwards): """ Site 태그 추가 """ sites = kwards['sites'] tags = self.request.data.get('tags') with transaction.atomic(): '''트랜젝션 시작''' created_tags = [Tag.objects.get_or_create(name=tag)[0] for tag in tags] [tag.site.add(site.id) for tag in created_tags for site in sites] return Response({'msg':'Add tag successfully'}, status=status.HTTP_200_OK)
'ISSUE > Django' 카테고리의 다른 글
[ISSUE] Tag 포함된 Site 모델의 serialize 처리 (0) 2023.05.06 [ISSUE] ManytoMany 관계를 가진 두 모델 Bulk Create 작업 (1) 2023.05.06 [ISSUE] signup AbstractBaseUser class (0) 2023.05.05 다음글이전글이전 글이 없습니다.댓글
스킨 업데이트 안내
현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)