API Document: https://docs.djangoproject.com/en/5.0/ref/models/querysets/
장고의 orm이라 볼 수 있다. 그만큼 쿼리에서의 많은 메소드들을 지원한다. 공식 문서의 메소드 리스트를 일부 캡처한 모습이다.
자세한 내용은 위의 API 문서를 참고하자.
우리는 여기서 쿼리셋을 집중 탐구 해보도록 한다.
QuerySet
쿼리셋은 데이터베이스를 통과하는 모든 것에 대한 구성, 필터, 슬라이스 등을 지원한다.
Iteration
Iterable의 성격을 가지고 있어 for 문에서 호출이 가능하다.
for e in Entry.objects.all():
print(e.headline)
하지만 모든 것을 불러오는 메소드 이므로 한 개 이상일 때만 결과를 볼 수 있으니 exists() 메소드를 꼭 사용하자.
Asynchronous
비동기도 지원하기 때문에 async 또한 사용이 가능하다.
async for e in Entry.objects.all():
results.append(e)
Slicing
limiting이라 볼 수 있다. 파이썬의 array-slicing syntax를 지원한다. 또한 step 파라미터를 사용하면 리스트를 리턴 받을 수 있다. 자세한 내용은 해당 링크를 참조한다. https://docs.djangoproject.com/en/5.0/topics/db/queries/#limiting-querysets
Pickling/Caching
Pickling을 이용한 Caching이 가능하다. 미리 Picked 해두었던 스트링을 아래와 같이 쿼리에 넣어준다. Pickle을 이용한 캐싱은 오랜 시간 저장하는 전략에는 적절하지 않은 점을 참고해야 한다.
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
repr()
python의 repr과 같다. repr은 eval을 사용해서 다시 사용하곤 하는데 여기선
This is for convenience in the Python interactive interpreter, so you can immediately see your results when using the API interactively.
이라 한다. 인터렉티브한 파이썬에서 편의를 위해 제공 하는 것 같다.
len()
오브젝트의 길이를 반환한다. 실제 객체를 가져온 후 갯수를 세는 것은 비효율적이므로 count() 함수 또한 제공한다.
list()
리스트 형태로 형변환이 가능하다.
entry_list = list(Entry.objects.all())
bool()
불쿼리가 가능하다. 필드의 값을 이용해 필터링을 한다.
if Entry.objects.filter(headline="Test"):
print("There is at least one Entry with the headline Test")
exists()
객체가 존재하는지 확인하는 용이라면 bool() 보단 exists()가 더 유용하다.
QuerySet API
class QuerySet(model=None, query=None, using=None, hints=None)¶
orderd
order_by와 같은 절로 정렬이 되어 있으면 True, 아니면 False
db
해당 쿼리에 사용될 db
QuerySet Methods
쿼리셋의 메소드들은 새로운 쿼리셋을 반환한다. 해당 쿼리셋을 통해서 체이닝 형태로 쿼리 절을 이어갈 수 있다.
filter lookups
filter()
filter(*args, **kwargs)¶
where절과 유사하다 볼 수 있다. 매우 자주 사용하게 될 메소드. **kwargs에서 필드와 매핑한다.
exclude()
exclude(*args, **kwargs)¶
조건과 일치하지 않는 값들을 가져온다.
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline="Hello")
위 코드는 아래의 쿼리와 매칭된다.
SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
And 조건을 체이닝해서 사용할 수도 있는데 이는 아래와 같다.
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline="Hello")
체이닝 된 쿼리는 아래와 같다.
SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'
OR statements와 같은 복잡한 쿼리는 Qobjects를 사용하며 아래 링크 참조https://docs.djangoproject.com/en/5.0/ref/models/querysets/#django.db.models.Q
get()
get(*args, **kwargs)¶
aget(*args, **kwargs)¶
aget은 Asynchronous 이다. lookup 파라미터들과 일치하는 한 개의 오브젝트를 가져온다. unique를 보증할 수 있는 파라미터들을 사용해야 한다. 예를 들어 pk나 unique constraint를 사용한다.
Entry.objects.get(id=1)
Entry.objects.get(Q(blog=blog) & Q(entry_number=1))
filter에서 이미 unique가 보증된 상태면 아래와 같이 get을 사용해 한 개만 가져올 수 있다. 이는 filter를 푸는 수고를 덜어준다.
Entry.objects.filter(pk=1).get()
존재하지 않는 조건을 제공하면 Model.DoesNotExist exception을 raise 한다.
Entry.objects.get(id=-999) # raises Entry.DoesNotExist
1개 초과의 많은 객체를 가진 조건을 제공하면 Model.MultipleObjectsReturned exception을 raise 한다.
Entry.objects.get(name="A Duplicated Name") # raises Entry.MultipleObjectsReturned
해당 에러들을 핸들링 하기 위해선 아래와 같이 예외 처리를 해준다.
from django.core.exceptions import ObjectDoesNotExist
try:
blog = Blog.objects.get(id=1)
entry = Entry.objects.get(blog=blog, entry_number=1)
except ObjectDoesNotExist:
print("Either the blog or entry doesn't exist.")
'Backend > Django' 카테고리의 다른 글
Django 멀티 디비 설정 (0) | 2024.03.13 |
---|---|
Django order_by와 annotate, extra 활용 (0) | 2024.03.13 |
Django Serializer의 Fields (1) | 2024.03.12 |
Django의 create()와 perform_create() (1) | 2024.03.12 |
Django Tutorial 6: ViewSets & Routers (0) | 2024.03.12 |