QuerySet vs QueryDict 차이점

권수민·2023년 9월 22일
1

먼저 QuerySet vs QueryDict 의 차이점부터 알아보려한다.

이 두가지는 장고에서 제공하는 중요한 클래스로, 다른 목적과 특성을 가지고 있다.

<QuerySet:>

목적:
-데이터베이스 쿼리의 결과를 나타내는 객체
-주로 Django ORM을 사용하여 데이터베이스에서 데이터를 조회할 때 사용한다.
예)all_posts = Post.objects.all()
=> QuerySet 반환
즉, ORM을 사용하는 코드(Objects)는 다 queryset을 반환한다고 보면된다.

특성:

  1. QuerySet은 게으른 평가(lazy evaluation)를 사용한다고 말하는데, 이 의미는 바로 데이터를 가져오는 것이 아니라 QuerySet을 가져오고 그것을 루프나 특정 메소드를 실행하였을때 실제 데이터에 접근하여 데이터를 가져온다는 의미입니다. 즉, 필요한 순간까지 데이터베이스 쿼리의 실행을 연기하는 방식으로 생가가면 될것 같습니다.

  2. filter(), exclude(), annotate() 등 다양한 메서드를 제공하여 데이터베이스 쿼리를 체인(chain)으로 연결할 수 있다.
    => 이 체인이라는 의미는 그냥 추가로 덧붙혀 필요한 쿼리를 만들어 낸다는 의미로 최종적으로 원하는 조건의 데이터만 불러올 수 있게 한다는 의미로 받아들이면 편할 것 같습니다.

  3. QuerySet은 내부적으로 캐시기능을 지원합니다. 즉, 이미 불러온 결과는 객체 내 캐시되어 캐시된 queryset객체에 다시 접근 = 동일한 쿼리 결과를 재사용하려할때 이미 캐시된 결과를 재사용하는 것입니다

  4. 데이터베이스의 모델 레코드(인스턴스)들의 리스트와 유사하게 동작합니다.
    Queryset은 리스트라 칭하기는 어렵지만 리스트와 같은 형태의 객체로 그 모델들의 인스턴스의 집합은 queryset의 형태로 반환되니 그리 칭하는것.

예시를 들어보겠습니다.

먼저 쿼리셋을 생성하기위해 모델 인스턴스를 만들건데요

posts = Post.objects.filter(published_date__year=2023).exclude(title__contains="Draft").order_by('-published_date')

여기서 이것을 불러왔다고 하여 실제로 데이터가 불러온것이아니라,쿼리셋의 상태로만 되어있습니다.

여기서

QuerySet을 반복할 때 (예: for post in posts:)
QuerySet의 길이를 조회할 때 (예: len(posts))
QuerySet을 명시적으로 평가할 때 (예: list(posts))
QuerySet의 특정 아이템에 접근할 때 (예: posts[0])

와 같이 어떠한 메소드들이나 루프를 통해서 접근하므로써 실행이 되어,
데이터를 불러온는 것이라고 설명할 수 있겠습니다.

posts = Post.objects.all()  
# 이 시점에서는 아직 데이터베이스에 쿼리를 실행하지 않았다.

for post in posts:  
# 여기에서 QuerySet이 평가되고, => late evaluation
# 데이터베이스에 쿼리가 실행됩니다. => 데이터 가져오는것
    print(post.title)

first_post = posts[0] 
# 인덱싱을 사용하여 특정 레코드에 접근할 수 있습니다.

<슬라이싱 사용해서 해당 부분만 가져오기>

recent_posts = Post.objects.all()[:5]  # 처음 5개의 포스트만 가져옵니다.

<명시적으로 쿼리셋 리스트로 변환>

posts_list = list(Post.objects.all())
 

<QueryDict:>

목적:

QueryDict는 HTTP 요청에서 전달된 GET 또는 POST 데이터를 처리하기 위한 특수한 딕셔너리입니다.

특성:
HTTP 요청에서 하나의 키에 여러 개의 값을 가질 수 있습니다 (예: ?key=value1&key=value2). => MultiValueDict()

QueryDict는 이러한 여러 값을 처리할 수 있습니다.

QueryDict는 immutable(불변)로 기본 설정되어 있습니다.
값을 변경하려면 copy() 메서드를 사용하여 mutable(변경 가능한) 복사본을 만들어야 합니다.

get(), getlist(), setdefault() 등의 특수한 메서드를 제공하여 여러 값을 처리할 수 있습니다.

주로 request.GET 또는 request.POST를 통해 접근합니다.

예로 저번 포스팅에 사용된 것을 그대로 불러와서 다시 사용해 설명해 보겠습니다.

post = Post.objects.get(id = post_id) 
# QueryDict 반환
post_data = request.POST.copy()
# request.POST는 QueryDict 타입으로 immutable(불변)이므로 복사해서 사용

post_data['post_id'] = post.id
post_data['text'] = "추가적으로 넣고 싶은 값"
#이렇게 직접적으로 불러와 변경 

image_form = ImageForm(data=post_data, files=request.FILES)

음 좀더 자세히 설명하면

1.HTTP요청에서 QueryDict사용

url 요청 :

http://example.com/
?name=John&hobby=reading&hobby=traveling 
#이 밑에 줄에 있는게 넘어간다 request 요청으로 

request.GET으로 받아와서

def example_view(request):
    names = request.GET.get('name') 
    # 'John'
    hobbies = request.GET.getlist('hobby') 
    # ['reading', 'traveling'] 값을 반환하겠지
    ...

2. QueryDict 직접 생성하기

from django.http import QueryDict

data = QueryDict('name=John&hobby=reading&hobby=traveling')
name = data.get('name')  # 'John'
hobbies = data.getlist('hobby')  # ['reading', 'traveling']

쿼리딕을 불러와서 직접 쿼리값을 전달해주는것.

3. QuertDict는 불변이다.

이 값은 딕셔너리 같은 객체이지 딕셔너리는 아닙니다.
안전하고 실수로 원본요청 데이터의 변경을 방지하기 위한 특성입니다.

mutable_data = data.copy()
mutable_data['name'] = 'Jane'

그렇기에 한 키에 대한 여러값을 처리할 수 있는 기능을 제공하면서,
기본적으로 불변성을 가집니다.

<요약>

한마디로

Queryset:
장고의 ORM을 사용할때 반환되는 값의 형태로, 리스트의 형태로 받아오지만 리스트는 아니고, 바로 데이터를 가져오지않고 어떠한 루프나 메소드로 직접 실행되어야 데이터값을 가져오는 느린평가의 기능을 가지고 있고, 캐시기능이 내장되어 성능저하없이 효율적으로 작동.

 from your_app.models import YourModel
 queryset = YourModel.objects.all()
 queryset
 
==> 값 : <QuerySet [<YourModel: ModelObject1>, <YourModel: ModelObject2>, ...]>

QuertDict:
딕셔너리형태와 비슷하지만 딕셔너리는 아니고, 불변성을 가지며, 한 키에 여러값을 넣을 수 있는 MultiValueDict()로, 주로 HTTP요청처리할때 사용한다.

직접 쿼리딕을 객체생성시

from django.http import QueryDict
q = QueryDict('name=John&hobby=reading&hobby=traveling')
print(q)

==> 값 : <QueryDict: {'name': ['John'], 'hobby': ['reading', 'traveling']}>

profile
초보개발자

0개의 댓글