First written: 22-11-21
Uploaded: 22-11-28
Last modified: 23-02-27
Django에서는 Post.objects.all()
과 같은 방식으로 ORM을 활용하여 굳이 SQLite3의 문법을 적어주지 않고도 편하게 Query문을 활용할 수 있다. 이런 것들을 QuerySet이라고 말하는데, 오늘은 그 QuerySet에 대해서 자주 쓰이는 것들을 살펴보기로 하자.
QuerySet API에는 QuerySet을 반환하는 메서드와 그렇지 않은 메서드가 섞여있다. 이들을 각각 따로 살펴보도록 하자.
우선 QuerySet을 반환하지 않는 메서드들을 보자. 특별한 이유가 있는 것은 아니고, 이쪽이 훨씬 양이 적어서(실제로 docuementation에 나온 양은 비슷한 것 같은데, 자주 쓰이는 것들만 살펴본다고 했을 때에는 이쪽이 양이 더 적은 게 맞다) 그렇다.
# 여러 개를 return하는 경우
Entry.objects.get(id=1)
Entry.objects.get(Q(author=author) & Q(address_code=101))
# 하나만 return하여 get() 메서드에 조건이 없어도 되는 경우
Entry.objects.filter(pk=pk).get()
parameter의 조건에 맞는 object를 반환한다.
만일 앞의 QuerySet이 확실히 하나만을 return한다면, 조건을 주지 않아도 된다.
p = Person.objects.create(first_name="Hello", last_name="World")
객체를 만들고 저장하는 것까지 한꺼번에 해준다 위의 코드는 아래와 같이 된다.
p = Person(first_name="Hello", last_name="World")
p.save(force_insert=True)
book = Book.chapters.get_or_create(title="How to do Django", author="Tim Howard", defaults{'version': 3})
있으면 해당 객체를 가져오고, 아니면 객체를 만들어 DB에 저장한다.
위의 코드는 아래와 같이 된다.
try:
bood = Book.objects.get(title="How to do Django", author="Tim Howard")
except Book.DoesNotExist:
bood = Book(title="How to do Django", author="Tim Howard", version=3)
bood.save()
비슷한 메서드로 update_or_create(defaults=None, **kwargs)
가 있다.
Entry.objects.filter(musicion="Hystone").count()
QuerySet에 담긴 객체의 수를 반환한다. 자주 쓰인다.
Entry.objects.latest('join_date')
주어진 필드를 기준으로 가장 최신의 객체를 반환한다. 여러 필드를 기반으로 선택도 가능하다.
비슷한 메서드로 earliest(*fields)
, first()
, last()
등이 있다.
from django.db.models import Sum
q = Order.objects.aggregate(total_price=Sum('price'))
쿼리셋 전체를 계산한 값들을 (averages, sums 등)을 딕셔너리 형태로 반환한다.
이를테면 {total_price: 262200}
와 같은 결과를 반환한다.
if Book.objects.filter(id=id).exists():
해당 QuerySet이 객체를 지니고 있으면 True, 아니면 False를 리턴한다.
비슷한 메서드로 contains(obj)
가 있다.
Employee.objects.filter(location="Seoul").update(holiday=True)
선택된 QuerySet에 담긴 모든 객체의 필드를 업데이트한다.
Article.objects.get(pk=1).delete()
해당 QuerySet에 담긴 모든 객체를 삭제한다.
이번에는 QuerySet을 반환하는 메서드들이다.
Entry.objects.filter(name='Lennon')
조건에 맞는 objects들만 가진 QuerySet을 반환한다.
반대되는 것으로 exclude(*args, **kwarg)
가 있다.
User.objects.annotate(first=Substr("first_name", 1, 1), last=Substr("last_name", 1, 1))
(보통은 새로운 계산식 때문에) QuerySet에서 새로 계산되어 생성된 column 이름을 지정해준다.
종종 보기 안 좋은 column 이름 때문에 그냥 이름을 바꾸는 용도로 사용되기도 한다.
비슷한 메서드로 alias(*args, **kwargs)
가 있다.
User.objects.order_by('-join_date', 'pk')
조건의 오름차순/내림차순에 따라 정렬한 QuerySet을 반환한다.
비슷한 메서드로 reverse()
가 있다.
Books.objects.distinct('version')
중복행을 제거한 뒤 QuerySet을 반환한다.
Book.objects.filter(title__startswith='British')
딕셔너리를 반환하는 QuerySet을 반환한다.
이를테면 위의 결과는 <QuerySet [<Blog: British Person, Sahara>]>
와 같을 수 있다.
이해를 위해 좀 더 보자.
Book.objects.filter(title__startswith='British').values()
위의 결과는 <QuerySet [{'id': 31, 'title': 'British Person, Sahara', 'published_at': '2022-10-10'}]>
와 같을 수 있다.
비슷한 메서드로 values_list(*fields, flat=False, named=False)
를 들 수 있다.
all_companies = Company.objects.all()
말 그대로 현재 QuerySet의 복사본을 그대로 리턴한다.
only_in_qs1 = qs1.difference(qs2, qs3)
다른 QuerySet에는 절대 없는 objects들로 이루어진 QuerySet을 반환한다.
같이 살펴볼만한 메서드로 union(*other_qs, all=False)
, intersection(*other_qs)
등이 있다.