Django 14. QuerySet API 3

jiffydev·2020년 11월 10일
0

들어가기 전에

이 포스팅에서 사용한 데이터들은 이곳 또는 공식문서가 원 출처임을 밝혀 둔다.
한편 쿼리셋 메소드는 종류가 많고 그 기능도 여러가지이므로 여기서 다 다루기는 어렵다. 이 포스팅에서는 기본적인 메소드 위주로 언급하고, 언급되지 않은 메소드에 대해서는 공식문서를 확인하면 더 자세히 알 수 있다.

QuerySet을 반환하지 않는 메소드 1탄

1. get(**kwargs)

filter/all 메소드와 함께 데이터베이스에서 데이터를 가져오는 메소드 3대장이다. 다만 get은 쿼리셋(데이터 여러개의 집합)을 가져오는 것이 아니라 객체(조건에 해당하는 인스턴스 하나)를 가져오는 것이기 때문에, 조건에 해당하는 객체가 여러개라면 MultipleObjectsReturned에러가 발생한다. 따라서 조건을 설정할 때 반드시 unique한 객체가 나오도록 잘 설정해야 한다. (보통은 id나 unique=True가 설정된 필드)

2. create(**kwargs)

객체를 만드는 메소드이며, 저장까지 한번에 해주는 매우 편리한 메소드이다.

p = Person.objects.create(first_name="Bruce", last_name="Springsteen")

3. get_or_create(defaults=None, **kwargs)

이름에서도 알 수 있듯, 객체가 있다면 get으로 가져오고 없다면 새로운 객체를 생성한다. 리턴값은 (object, created)의 튜플형식이며 object에는 가져오거나 생성된 객체가 들어있고, created는 객체가 생성됐다면 True, 가져왔다면 False값을 가진다.

이 메소드를 사용하는 이유는 복수의 요청이 왔을 때 race condition이 발생하여 객체가 생성되지 않은 것을 보고 각 요청이 객체를 생성하여 중복이 발생하는 것을 막기 위해서이다.

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()
obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

위와 같은 예외처리를 해 주지 않아도 get_or_create를 사용하여 동일한 기능을 구현할 수 있다.

다만 get_or_create이 race condition 상황에서 만능은 아닌 것이, 이 메소드는 atomic(원자성, 트랜잭션은 모두 성공하거나 실패해야 함)하기 때문이다. 메소드의 특성상 동시에 메소드를 실행했을 때 객체를 get 할 수 없다면 반드시 create 해야 하고, 데이터베이스 상에서 kwargs가 unique할 것으로 가정하고 있으므로, 중복 생성이 될 가능성이 있다. 그렇기 때문에 필드에 unique=True 속성을 설정하거나 unique_together로 복수의 필드가 unique하도록 설정해야 한다.

4. count()

쿼리셋 안의 객체 수를 정수형으로 리턴하는 메소드이다. len()으로 길이를 구하면 숫자는 똑같이 나오지만, count()는 개수만 세어주는 반면 len()은 모든 레코드를 불러와야 하기 때문에, 공식문서에도 언급되어 있듯 객체 수만 구한다면 count()를 쓰는 것을 추천한다. (객체를 결국 불러와야 한다면 그냥 len()을 써도 무관하다)

profile
잘 & 열심히 살고싶은 개발자

0개의 댓글