국내, 해외 어디를 가더라도 항공, 숙박, 티켓, 투어, 액티비티 여행 예약 플랫폼 마이리얼트립! '마이 리얼 트립'(https://www.myrealtrip.com/) 웹사이트 클론.
- 회원가입 (소셜)
- 로그인( 소셜)
- 상세페이지 - 옵션 선택
- 카테고리리스트
- 메인리스트 - 랜드마크
- 상세페이지 - 리뷰
- 상세페이지 - 메인페이지 로직 적용
- 위시리스트
- 검색기능
Product Detail 페이지 구현
(DB Hit 줄이기 위해 Prefetch 사용)
class ProductView(View):
def get(self, request, product_id):
product = Product.objects.filter(id=product_id).prefetch_related(
'review_set', 'review_set__user','review_set__reviewimage_set',
'option_set', 'option_set__date_set').first()
if not product:
return JsonResponse({'message':'NOT EXIST'}, status=404)
total_score = product.review_set.aggregate(Avg('score'))['score__avg']
result = {
'name' : product.name,
'price' : product.price,
'discount' : product.discount,
'main_image' : product.main_image,
'detail_image' : product.detail_image,
'total_score' : total_score if total_score != None else 0,
'total_review' : product.review_set.count() if product.review_set.count() > 0 else 0,
'reviews' : [{
'user' : review.user.name,
'contents' : review.contents,
'score' : review.score,
'manager_text' : review.manager_text,
'create_at' : review.create_at,
'update_at' : review.update_at,
'images' : [data.image for data in review.reviewimage_set.all()]
}for review in product.review_set.all()],
'options' : [{
'name' : option.name,
'price' : option.price,
'dates' : [data.date for data in option.date_set.all()]
} for option in product.option_set.all()]
}
return JsonResponse({'product':result}, status=200)
Option 선택 기능
class OptionView(View):
def post(self, request):
try:
data = json.loads(request.body)
date = Date.objects.get(id=data['option_id'])
result = (True if date.count > data['count'] else False)
return JsonResponse({'status':result}, status=200)
except Date.DoesNotExist:
return JsonResponse({'message':'NOT EXIST'}, status=404)
Review View 기능
class ReviewView(View):
def get(self, request):
product_id = request.GET.get('product_id')
offset = int(request.GET.get('offset',0))
limit = int(request.GET.get('limit',3))
reviews = Review.objects.filter(product_id=product_id).prefetch_related('user','reviewimage_set')[offset:limit]
result = [{
'user' : review.user.name,
'contents' : review.contents,
'score' : review.score,
'manager_text' : review.manager_text,
'create_at' : review.create_at,
'update_at' : review.update_at,
'images' : [data.image for data in review.reviewimage_set.all()]
} for review in reviews]
return JsonResponse({'reviews':result}, status=200)
Test.py 작성
class ProductTestCase(TestCase):
@classmethod
def setUpTestData(cls):
MainCategory.objects.create(id=1,name='test')
SubCategory.objects.create(id=1,name='test', maincategory_id=1)
Region.objects.create(id=1,name='test')
User.objects.create(id=1,name='test', password='123')
Product.objects.create(
id=1,
name='test',
price=Decimal(123.00),
discount=0.1,
main_image='test',
detail_image='test',
subcategory_id=1,
region_id=1
)
Option.objects.create(
id=1,
name='test',
price=Decimal(1),
product_id=1
)
Date.objects.create(
id=1,
date=datetime.strptime('2021-06-26', '%Y-%m-%d'),
count=1,
option_id=1
)
Review.objects.create(
id=1,
contents='test',
score=1,
manager_text='test',
product_id=1,
user_id=1
)
ReviewImage.objects.create(id=1, image='test', review_id=1)
def tearDown(self):
User.objects.all().delete()
MainCategory.objects.all().delete()
SubCategory.objects.all().delete()
Region.objects.all().delete()
Product.objects.all().delete()
Date.objects.all().delete()
Option.objects.all().delete()
Review.objects.all().delete()
ReviewImage.objects.all().delete()
def test_get_product(self):
client = Client()
data = {
'name' : 'test',
'price' : '123.00',
'discount' : 0.1,
'main_image' : 'test',
'detail_image' : 'test',
'total_score' : 1.0,
'total_review' : 1,
'reviews' : [{
'user' : 'test',
'contents' : 'test',
'score' : 1,
'manager_text': 'test',
'create_at' : '',
'update_at' : '',
'images' : ['test']
}],
'options' : [{
'name' : 'test',
'price' : '1.00',
'dates' : ['2021-06-26']
}]
}
response = client.get('/products/1', content_type = 'application/json')
response_data = response.json()
data['reviews'][0]['create_at'] = response_data['product']['reviews'][0]['create_at']
data['reviews'][0]['update_at'] = response_data['product']['reviews'][0]['update_at']
self.assertEqual(response.json(),{'product':data})
self.assertEqual(response.status_code, 200)
def test_get_product_error(self):
client = Client()
response = client.get('/products/2', content_type = 'application/json')
self.assertEqual(response.json(),{'message':'NOT EXIST'})
self.assertEqual(response.status_code, 404)
- Trello
- Git
- GitHub
- Slack
- 데이터베이스 모델링의 중요성
- 협업 및 소통
- 리펙토링