기획 의도, 화면, 코드, 테스트 코드, 어려웠던 점, 해결방법, 느낀점 등을 설명한다.
1. 레스토랑
- 기획 의도
- 특정 카테고리를 클릭하면 그에 맞는 레스토랑 리스트가 출력되는 것이 목표
- 화면
- 코드
카테고리를 클릭하면 'category/<int:category_id>/restaurant/'가 호출되고 레스토랑 리스트 화면이 나온다.
저 경로로 요청이 들어오면 템플릿 렌더링을 할 때 category_id를 html 파일에 넘겨준다. 그 html 파일에선 ajax로 api 호출을 하는데 "/api/category/" + {{ category_id }} +"/restaurant/" 이렇게 호출한다. 그러면 api 디렉토리의 urls.py에선 패턴을 찾고 일치하는 게 있으면 views.RestaurantListAPIView.as_view(), 이렇게 클래스 기반 뷰를 함수로 호출한다.
class RestaurantListAPIView(View):
def get(self, request, *args, **kwargs):
category_id = self.kwargs['category_id']
if category_id == CategoryNum.ALL_ID:
restaurant_list = Restaurant.objects.all().values(
'pk', 'title', 'min_order_price', 'estimated_delivery_time', 'img',
)
else:
restaurant_list = Restaurant.objects.filter(category=category_id).values(
'pk', 'title', 'min_order_price', 'estimated_delivery_time', 'img',
)
if not restaurant_list:
return HttpResponse(
json.dumps({"message": "레스토랑 리스트가 존재하지 않습니다.", }),
status=HTTPStatus.NOT_FOUND,
content_type='application/json',
)
restaurant_list = list(restaurant_list, )
json_data = {
'restaurant_list': restaurant_list,
'category_id': category_id,
}
json_data = json.dumps(json_data, cls=DateTimeEncoder)
return HttpResponse(
json_data,
content_type='application/json',
)
category_id가 key가 되고 값이 value인 dict가 넘어온다. 그래서 값을 받을 때 kwargs(keyword arguments)에서 key(category_id)를 사용한다.
카테고리 ID에 맞는 레스토랑들을 찾아서 restaurant_list에 넣는다.
- 테스트 코드
레스토랑 단순 보여주는 부분이라 안짠듯
- 어려웠던 점
배달예상시간의 타입은 datetimefield인데 출력해야할 형식은 H:M이었다.
- 해결 방법
json.dumps()에서 DateTimeEncoder를 사용했다.
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
return obj.strftime('%H:%M')
- 느낀점
인코더 클래스를 사용해서 문자열 형식의 시간을 반환해주는 게 멋졌다.
2. 레스토랑 디테일
- 기획 의도
특정 레스토랑을 클릭하면 레스토랑 디테일 페이지가 나오고 정보가 나온다.
- 화면
- 코드
레스토랑을 누르면 'category/<int:category_id>/restaurant/<int:restaurant_id>/'이게 호출되고 레스토랑 기본키 값으로 DB에서 레스토랑을 찾게 된다.
class RestaurantDetailAPIView(View):
def get(self, request, *args, **kwargs):
user = request.user
restaurant_id = self.kwargs['restaurant_id']
try:
restaurant_detail = Restaurant.objects.filter(id=restaurant_id).values(
'name', 'img', 'min_order_price', 'order_way', 'owner', 'title', 'operation_start_hour',
'operation_end_hour',
'tel', 'origin', 'delivery_charge', 'info', 'estimated_delivery_time',
)
if not restaurant_detail:
return HttpResponse(
json.dumps({"message": "해당 레스토랑이 없습니다.", }),
status=HTTPStatus.NOT_FOUND,
content_type='application/json',
)
restaurant_detail= json.dumps(list(restaurant_detail, ), cls=DateTimeEncoder)
if request.user.is_authenticated:
if user.subscribed_restaurants.filter(pk=restaurant_id):
subscribe_flag = False
json_data = {
'restaurant_detail': restaurant_detail,
'user_addr': request.user.address,
'subscribe_flag': subscribe_flag,
}
else:
subscribe_flag = True
json_data = {
'restaurant_detail': restaurant_detail,
'user_addr': request.user.address,
'subscribe_flag': subscribe_flag,
}
else:
json_data = {
'restaurant_detail': restaurant_detail,
}
return HttpResponse(
json.dumps(json_data),
content_type='application/json',
)
except Restaurant.DoesNotExist:
json_data = {
"message": "레스토랑이 없습니다.",
}
return JsonResponse(
json_data,
status=HTTPStatus.BAD_REQUEST,
)
- 테스트 코드
class RestaurantTestClass(TestCase):
def setUp(self):
self.category=Category.objects.create(name='치킨',img='restaurant/chicken.jpg')
self.restaurant=Restaurant.objects.create(
name='굽내치킨',title='굽내치킨-서초점', estimated_delivery_time='2019-01-01 00:20',
min_order_price=10000, delivery_charge=1000, operation_end_hour='2019-01-01 10:00',
operation_start_hour='2019-01-01 10:00', )
def test_restaurant_detail_page_should_be_opened_on_request(self):
'''
category id를 보낼 시 레스토랑 상세 페이지 열기
'''
# Given
url = reverse("restaurant:restaurant_detail", kwargs={
'category_id': self.category.id, 'restaurant_id': self.restaurant.id
})
# When
response = self.client.get(url)
# Then
self.assertEqual(response.status_code, HTTPStatus.OK)
def test_restaurant_detail_api_should_return_datas_on_valid_request(self):
'''
유효한 restaurant id 보낼 시 레스토랑에 관한 데이터 응답하기
'''
# Given
url = reverse("restaurant_api:restaurant_detail_api", kwargs={
'category_id': self.category.id, 'restaurant_id': self.restaurant.id
})
# When
response = self.client.get(url)
# Then
self.assertEqual(response.status_code, HTTPStatus.OK)
def test_restaurant_detail_api_should_return_404_on_invalid_request(self):
'''
유효하지 않은 restaurant id 보낼 시 404 에러 출력하기
'''
# Given
not_exist_id = 99999
url = reverse("restaurant_api:restaurant_detail_api", kwargs={
'category_id': not_exist_id, 'restaurant_id': not_exist_id
})
# When
response = self.client.get(url)
# Then
self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND)
- 어려웠던 점
try except로 예외처리를 해야 했는데 except에서 어떤 코드를 작성해서 예외를 표시해야 하는지 헷갈렸다.
- 해결방법
레스토랑에 대한 결과가 없는 경우 .DoesNotExist를 사용했다.
- 느낀점
try except를 더 세분화해서 예외처리를 하면 나중에 오류가 났을 때 어디서 오류가 났는지 파악하기 쉽다.
'인턴 프로젝트' 카테고리의 다른 글
미니 요기요 프로젝트(5) - 레스토랑 구독하기, 구독 중인 레스토랑 (0) | 2019.07.24 |
---|---|
미니 요기요 프로젝트(4) - 날씨별 잘 팔린 메뉴 (0) | 2019.07.24 |
미니 요기요 프로젝트(3) - 메뉴, 메뉴 디테일 (0) | 2019.07.23 |
미니 요기요 프로젝트(1) - 카테고리 (0) | 2019.07.23 |
미니 요기요 프로젝트(0) - 개요 (0) | 2019.07.23 |