일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 스코프
- manytomanyfield
- 실행 컨텍스트
- wecode
- javascript
- Jest
- bcrypt
- OSI7계층
- JWT
- nodeJS
- async/await
- CORS
- 호이스팅
- 노드
- status code
- Django
- crud2
- 자바스크립트
- node
- on_delete
- 장고초기세팅
- TypeError: this.boardRepository.createBoard is not a function
- rebase
- 트랜잭션
- typescript
- pm2
- docker
- westagram
- 프로미스
- django westagram
- Today
- Total
될때까지
((TURTLE HOME)) 5일차 : ProductDetailView 본문
첫번째 시도
- 클라이언트로부터 product_id를 받는다. 전달된 product_id가 DB에 저장되어있는 Product 객체들의 id와 같은가 조회를 하고
- 만약 Product객체들 중 일치하는 객체가 없다면 Product.DoesNotExist에러를 만나 except로 처리가 들어간다. 이때 400 을 에러코드로 정했다.
- 400으로 처리한 이유는 400 Bad Request, 요청자체가 잘못된 접근이다는 판단이 들었다.
- 하지만 멘토님의 리뷰는 리소스가 없는 경우에는 404 Not Found를 사용한다 하셨다.
- 듣고보니 맞는 말, 요청한 Product 객체가 존재하지 않음 => 404 Not Found
두번째 시도(with 멘토님)
- Product.objects.get(id=product_id)로 인해 이미 product_id가 존재하는 객체가 필터링 된 상황이다.
- 그 상황에서 product.productoption_set.filter(product_id = product.id)라고 작성하면, 이미 product_id가 존재하는 상품 객체 중에, ProductOption테이블에서 product_id가 product.id와 일치하는 객체를 가져오라고 필터링을 하고 있다.
- 필터링이 불필요한 상황이다 왜냐 이미 get에서 id=product_id로 해서 product를 걸렀으니까!
- 그래서 위의 코드는 아래와 같이 수정이 된다.
ORM에 대한 개념이 100% 확실하게 자리잡지 않은 것 같다. 첫날보다는 덜하지만 그래도 여전히 허우적대고 있다(?). 그리고 HTTP 상태 코드에 대한 개념도 아직 모자라다. 주말에 시간을 내서 공부하고 넘어가야겠다!!
* 일주일 지나고 다시 작성하는 리뷰
음? 어떻게 'size' : option.size.name으로 가져올 수 있지? option에는 size_id가 있지 size는 없는데? 역시 동기나 멘토님께 여쭤보고 해결했던 코드는 머리에 깊게 남지 않는다. 다시 지려밟아보자(?)
상품 옵션을 어떻게 option.size.name으로 가져올 수 있을까? 상품 옵션 테이블에는 product_id와 size_id만 있을텐데? 어떻게 .을 사용해서 타고 다른 테이블에 있는 외래키가 연결이 될까?
정답은 내가 생성했던 ProductOption 테이블에 있다. ProductOption테이블에는 2개의 외래키가 연결되어 있는데, 이 필드의 이름은 'size'와 'product'로 만들었다. 그래서 ProductOption 테이블에는 'size'와 'price'라는 테이블 이름이 존재하는 것!' !!!
# products > models.py
class ProductOption(models.Model):
product = models.ForeignKey('Product', on_delete=models.CASCADE)
size = models.ForeignKey('Size', on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10, decimal_places=2)
class Meta:
db_table = 'products_options'
하지만 DB를 생성할 때는 해당 컬럼의 이름이 'size_id' , 'product_id'가 된다.
class ProductDetailView(View):
def get(self, request, product_id):
try:
product = Product.objects.get(id=product_id)
options = product.productoption_set.all()
result = {
'id' : product.id,
'name' : product.name,
'number' : product.number,
'description' : product.description,
'image_url' : product.image_url,
'sub_category_id': product.sub_category_id,
'options' : [{
'size' : option.size.name,
'price' : option.price
} for option in options]
}
return JsonResponse({'result':result}, status=200)
except Product.DoesNotExist:
return JsonResponse({'message':'Product does not exist.'}, status=404)
product에는 id가 클라이언트로 부터 전달받은 product_id와 일치하는 객체 1개가 담겨있다. 그럼 해당 객체와 ProductOption테이블을 _set을 사용하여 연결할 수 있다(역참조 사용). 그럼 product에 담긴 객체의 product_id가 ProductOption테이블에 있는 product_id와 동일한 객체들을 모두 가져와서(all()) options에 담는다.
리스트 컴프리헨션을 만나 product_id가 연결되어 있는 option 값 들 하나 하나(=가로값)의 size.name으로 해당 사이즈의 이름과 가격을 넣어주었다. (예를 들어 a이불커버 - 싱글 : 5000, 더블 : 7000, 퀸 : 8000, 킹 : 9000 경우 반복문을 돌면서 처음에는 싱글 : 5000이 담기고, 두번째에는 더블 : 7000이 담긴다)
정리하자면, 해당 테이블 안의 데이터 값 중 특정한 값을 가져오고 싶을때는 size_id와 같이 테이블의 컬럼이름값을 사용하여 가져올 수 있다. 그게 아니라 size테이블의 속성값(name)이 필요한 경우에는 dot notation을 써서 원하는 데이터를 가져올 수 있다.
'프로젝트 > wecode1차 : TURTLE-HOME' 카테고리의 다른 글
((TURTLE HOME)) 7일차 : ProductListView ordering 2/2 (0) | 2022.07.24 |
---|---|
((TURTLE HOME)) 6일차 : ProductListView 1/2 (0) | 2022.07.23 |
((TURTLE HOME)) 4일차 : SubCategoryView (0) | 2022.07.22 |
((TURTLE HOME)) 3일차 : CSV파일 생성 및 DB에 적용하기 (0) | 2022.07.20 |
((TURTLE HOME)) 2일차 : products app, 상품 모델링 (0) | 2022.07.19 |