이 글은 모범 사례로 배우는 Django 테크닉에 관한 명서 "Two Scoops of DJango"(대니얼 로이 그린펠드, 오드리 로이 그린펠드 저, 2016)를 읽고 요약 정리하여 작성한 것입니다. 이 책을 읽고 새로웠던 것, 기존에 잘 알지 못했던 것을 위주로 작성했습니다.
ObjectDoesNotExist
는 어떤 모델 객체에도 이용이 가능하다. 그러나, DoesNotExist는 특정 모델에서만 이용할 수 있다.get
으로 접근하는 경우 특정 모델을 가져오게 되는데 이 때 해당 객체가 없다면 DoesNotExist
를 사용할 수 있다.try:
return Product.objects.get(id=1234)
except Product.DeosNotExist:
raise OutOfStock(해당_재고가_없습니다)
쿼리가 하나 이상의 객체를 반환할 수도 있다면 MultipleObjectsReturned
예외를 이용할 수 있다.
- 위에 사용한 예시에서 예외 케이스를 추가할 수 있다. 여러 개의 객체가 반환되었다는 말은 데이터베이스에 이상이 있다는 뜻이다.
try:
return Product.objects.get(id=1234)
except Product.DeosNotExist:
raise OutOfStock(해당_재고가_없습니다)
except Product.MultipleObjectsReturned:
raise CorruptedDatabase(데이터베이스의_이상작동)
지연 연산은 데이터가 정말로 필요하기 전까지 장고가 SQL을 호출하지 않는 특징을 가리킨다. - 이에 대한 자세한 설명은 김성렬님의 PyCon 강의를 참고하는 것이 좋다.
여기에도 정리해 두었다.
데이터베이스는 데이터 관리와 가공에서 파이썬보다 월등히 빠르다. 따라서, 데이터를 호출한 뒤에 다시 한 번 더 파이썬으로 데이터를 가공하는 것이 과연 옳은 일일까?
from models.products import Product
products = []
for product in Product.objects.iterate():
if product.ordered > product.left:
products.append(product)
from django.db.models import F
from models.products import Product
products = Product.objects.filter(ordered__gt=F('left'))
ORM은 단순한 쿼리 작성 뿐만 아니라 모델에 대한 접근과 업데이트시 유효성 검사와 보안을 제공한다는 장점이 있다. 그러나, 로우 쿼리를 이용할 경우 ORM을 이용하는 경우보다 코드가 훨씬 간결해지고 단축된다면 로우 쿼리를 이용하자.
db_index=True
를 추가하면 된다.pg_stat_activity
를 이용하면 실제로 이용되는 인덱스들을 확인할 수 있다.
- 트랜잭션은 둘 또는 그 이상의 데이터베이스 업데이트를 단일화된 작업으로 처리하는 기법을 말한다.
- 하나의 수정 작업이 실패하면 트랜잭션 상의 모든 업데이트가 실패 이전 상태로 복구되는데 이를 롤백이라 하며, 트랜잭션은 롤백 또는 커밋의 상태로 존재한다.
DATABASES
설정에 ATOMIC_REQUESTS=True
설정을 추가할 것을 권장한다.transaction.non_atomic_requests()
로 데코레이팅 하는 것이 좋다.from django.db import transaction
from django.utils import timezone
from products.models import Product
@transaction.non_atomic_requests
def posting_product_status(requests, pk, status):
product = Product.objects.filter(pk=pk).first()
# 오토 커밋(장고 기본 설정)
product.latest_status_change_attempt = timezone.now()
product.save()
with transaction.atomic():
# 이 코드는 트랜잭션 안에서 실행 된다.
product.status = status
product.latest_status_change_success = timzone.now()
product.save()
return Response(status=status.HTTP_200_OK, data=data)
create()
, update()
, delete()
를 트랜잭션으로 처리하는 것은 유용하지 않다.참고자료
Two Scoops of DJango"(대니얼 로이 그린펠드, 오드리 로이 그린펠드 저, 2016)