장고에서 데이터를 수정하기 위해서는 views.py에 post
메소드 안에 작성된 모든 필드명을 받아야 한다.
(수정은 patch
나 put
메소드도 가능)
예를 들어 하나의 메소드 안에서 korean_name
, english_name
, description
, is_new
, category
를 수정할 수 있도록 작성했다고 한다면,
프론트 쪽에선 description
만 수정하고 싶더라도 5개 모두에 대한 정보를 넘겨줘야 수정이 가능하다. 아니면 KeyError
가 나고 수정되지 않는다.
그렇다고 description
만 수정하는 메소드를 따로 빼기에는 너무 비효율적이다.
하지만 바로 딕셔너리의 get
메소드를 이용한다면, KeyError
없이 일부 필드만 수정할 수 있다!
우선 views.py
에 POST 메소드로 특정 id의 product
정보를 수정하는 로직을 작성하였다.
class ProductDetailView(View):
def post(self, request, product_id):
data = json.loads(request.body)
category = Category.objects.get(name=data['category'])
product = Product.objects.get(id=product_id)
product.korean_name = data['korean_name']
product.english_name = data['english_name']
product.description = data['description']
product.is_new = data['is_new']
product.category = category
product.save()
return JsonResponse({'message': 'SUCCESS'}, status=201)
그리고 DB에는 아래의 정보가 이미 들어있다!
description
만 수정하고 싶다면?description
를 딸기의 상큼함
에서 스트로베리베리 상큼함
으로 변경하려고 한다.
http -v POST localhost:8000/products/product/5 description="스트로베리베리 상큼함"
이렇게 하면 될 것 같지만, 서버는 500
에러를 뿜어내고 장렬히 전사한다.
KeyError
가 났다고 하는데,
이유를 살펴보면 views.py
로직에서 작성한 모든 필드명을 보내주지 않아서 KeyError
가 난 것이다.
class ProductDetailView(View):
def post(self, request, product_id):
data = json.loads(request.body)
try:
category = Category.objects.get(name=data['category'])
product = Product.objects.get(id=product_id)
product.korean_name = data['korean_name']
product.english_name = data['english_name']
product.description = data['description']
product.is_new = data['is_new']
product.category = category
product.save()
return JsonResponse({'message': 'SUCCESS'}, status=201)
except KeyError:
return JsonResponse({'message':'INVALID_KEYS'}, status=400)
이렇게 로직을 변경하였다.
이제 KeyError
가 나도 500
에러를 뿜지 않고 INVALID_KEYS
메시지와 400
에러가 뜰 것이다.
http -v POST localhost:8000/products/product/5 description="스트로베리베리 상큼함"
하지만 try, except는 500에러만 처리할 뿐 DB의 정보는 수정되지 않았다.
(description
이 그대로 딸기의 상큼함
이다.)
다시 말해 바꾸고 싶지 않은 필드인 korean_name
, english_name
, is_new
, category
까지 적어줘야 한다는 것이다.
http -v POST localhost:8000/products/product/5 korean_name="딸기 요거트 블렌디드" english_name="Strawberry Yogurt Blended"
description="스트로베리베리 상큼함" is_new=0 category="블렌디드"
굳이굳이 다른 애들까지 다 적어서 보내주면 성공이다..!
DB에서도 잘 바꼈다.
(description
이 스트로베리베리 상큼함
으로 변경되었다.)
당연히 있다.
딕셔너리.get(키, 기본값) : 딕셔너리 안에 찾으려는 Key 값이 없을 경우 기본값을 대신 가져온다.
product.korean_name = data['korean_name'] 을
product.korean_name = data.get('korean_name', product.korean_name) 로 바꿔보았다.
product.korean_name = data['korean_name']은
프론트쪽에서 넘겨준 데이터(data
)에서 키값이 korean_name
인 값을 찾아 필드에 넣어주고, 만약 전달된 body에 korean_name
이라는 키가 없으면 에러를 발생시켰다.
반면,
product.korean_name = data.get('korean_name', product.korean_name)은
프론트쪽에서 넘겨준 데이터(data
)에서 korean_name
을 찾으면 넘겨주고, 만약 korean_name
이라는 키가 없으면 기존에 있던 값인 product.korean_name
을 사용하겠다는 의미이다.
class ProductDetailView(View):
def post(self, request, product_id):
data = json.loads(request.body)
category = Category.objects.get(name=data.get('category', product.category.name))
product = Product.objects.get(id=product_id)
product.korean_name = data.get('korean_name', product.korean_name)
product.english_name = data.get('english_name', product.english_name)
product.description = data.get('description', product.description)
product.is_new = data.get('is_new', product.is_new)
product.category = category
product.save()
return JsonResponse({'message': 'SUCCESS'}, status=201)
http -v POST localhost:8000/products/product/5 description="새콤달콤 신선한 딸기향 가득
description
만 던져줘도 오류가 나지 않고 성공이라 뜬다!
실제 데이터베이스에서도 수정되었다!
이 방법은 이 유투브 영상을 참고하여 작성하였다. 더 자세히 알고 싶으면 영상을 참고하자.