API 요청이 들어왔을 때 Views에서 바로 처리하는 것이 아니라 Service Layer를 로직에 추가하여 실제 기능과 API 응답처리를 나눠 관리하는 것
Service Layer를 추가함으로써 Veiws의 크기를 줄일 수 있고 기능별로 예외처리, 테스트코드 작성에 용이하다.
구현하고자 하는 앱에 service 폴더를 만들고 구현하고자하는 기능을 작성한다.
예시)
user
앱에Service
라는 폴더 생성 후user_service.py
에 기능 구현
# user.views.py
# 유저 CRUD 기능
class UserView(APIView):
...
# 회원 가입
def post(self, request):
user_serializer = UserSerializer(data=request.data)
if user_serializer.is_valid(): # validation
user_serializer.save() # create
return Response({'message': '저장 완료!'}, status=status.HTTP_200_OK)
return Response(user_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# user.service.user_service.py
def user_post_service(user_info: dict):
"""
사용자정보로 회원가입하는 함수
Args:
user_info (dict): 회원가입할 유저 정보
Raises:
Todo) 예외처리 작업중
"""
user_type_str = user_info.pop("user_type", "general")
user_type_obj = UserType.objects.get(user_type=user_type_str)
user_serializer = UserSerializer(data=user_info)
user_serializer.is_valid(raise_exception=True)
user_serializer.save(user_type=user_type_obj)
# user.views.py
from user.Service.user_service import (
user_post_service,
)
...
# 유저 CRUD 기능
class UserView(APIView):
...
# 회원가입 기능
def post(self, request):
try:
user_post_service(request.data)
return Response({"detail": "회원가입 성공"}, status=status.HTTP_200_OK)
except AssertionError:
return Response({"detail": "회원가입에 실패했습니다."}, status=status.HTTP_400_BAD_REQUEST)
회원가입 기능 테스트 - 정상 작동회원가입 기능과 회원가입 결과에 따른 예외처리 기능을 나눠서 처리 할 수 있다.
# user.tests.service.test_user_service.py
# 회원가입 기능 테스트
def test_user_create_service(self):
"""
회원가입 기능 테스트
case : 정상 작동
"""
user_info = {
"username": "test",
"password": "test_password",
"gender": "female",
"age": "45",
"phone": "010-1212-1212",
"user_type": "general"
}
count_1 = User.objects.all().count()
with self.assertNumQueries(5):
user_post_service(user_info)
count_2 = User.objects.all().count()
self.assertEqual(count_1 + 1, count_2)
# user.tests.service.test_user_service.py
def test_user_create_when_does_not_create_object(self):
"""
회원가입 기능 테스트
case : 유저 오브젝트가 제대로 생성되지 않았을 경우
"""
user_info = {
"username": "test",
"password": "test_password",
"gender": "female",
"age": "45",
"phone": "010-1212-1212",
"user_type": "general"
}
count_1 = User.objects.all().count()
with self.assertRaises(AssertionError):
with self.assertNumQueries(4):
user_post_service(user_info)
count_2 = User.objects.all().count()
with self.assertRaises(AssertionError):
self.assertNotEqual(count_1 + 1, count_2)
작성 코드 : https://github.com/PreOnBoarding/Bulletin_Board_Service