[Django] Django ORM Cookbook : 1

GreenBean·2021년 9월 30일
0

Django ORM Cookbook

목록 보기
1/8
post-thumbnail

Django ORM

Django ORM Cookbook


SQL 질의문 확인

  • 장고 ORM이 실행하는 실제 SQL 질의문 확인
    • str(queryset.query)
>>> queryset = Event.objects.filter(years_ago__gt=5)
>>> str(queryset.query)

SELECT "events_event"."id", "events_event"."epic_id","events_event"."details",
"events_event"."years_ago" FROM "events_event"
WHERE "events_event"."years_ago" > 5

OR 연산

  • OR 연산으로 여러 조건 중 하나라도 만족하는 행을 구해야 하는 경우
    • queryset_1 | queryset_2
    • filter(Q(<condition_1>)|Q(<condition_2>))
>>> queryset = User.objects.filter(first_name__startswith='R') | User.objects.filter(last_name__startswith='D')
>>> queryset

<QuerySet [<User: Ricky>, <User: Ritesh>, <User: Radha>, <User: Raghu>, <User: rishab>]>


>>> str(queryset.query)

SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
"auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
"auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
"auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)


>>> from django.db.models import Q
>>> qs = User.objects.filter(Q(first_name__startswith='R')|Q(last_name__startswith='D'))


# 두 방법 모두 생성되는 SQL 질의문은 완전히 동일
>>> str(qs.query)

SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
"auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
"auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
"auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
 WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)

AND 연산

  • AND 연산으로 여러 조건을 모두 만족하는 행을 구해야 하는 경우
    • queryset_1 & queryset_2
    • filter(<condition_1>, <condition_2>)
    • filter(Q(<condition_1>) & Q(<condition_2>))
>>> queryset_1 = User.objects.filter(first_name__startswith='R') & User.objects.filter(last_name__startswith='D')
>>> queryset_2 = User.objects.filter(first_name__startswith='R', last_name__startswith='D')

>>> from django.db.models import Q
>>> queryset_3 = User.objects.filter(Q(first_name__startswith='R') & Q(last_name__startswith='D'))


>>> str(queryset_1.query)

SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
"auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
"auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", 
"auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" 
WHERE ("auth_user"."first_name"::text LIKE R% AND "auth_user"."last_name"::text LIKE D%)

# 실제로 생성되는 SQL 질의문을 확인하여 검증
>>> str(queryset_1.query) == str(queryset_2.query) == str(queryset_3.query)

True

NOT 연산

  • 조건을 만족하지 않는 행을 구해야 하는 경우
    • exclude(<condition>)
    • filter(~Q(<condition>))
# 조건의 SQL 질의문
SELECT id, username, first_name, last_name, email FROM auth_user WHERE NOT id < 5;


>>> queryset = User.objects.exclude(id__lt=5)
>>> queryset

<QuerySet [<User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>


>>> from django.db.models import Q
>>> queryset = User.objects.filter(~Q(id__lt=5))
>>> queryst

<QuerySet [<User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>

UNION 연산

  • 장고 ORM에서 union 메서드를 이용해 쿼리셋을 합할 수 있음
    • 합하려는 쿼리셋의 모델이 서로 다른 경우, 각 쿼리셋에 포함된 필드와 데이터 유형이 서로 맞아야 함
    • union 메서드는 합하려는 쿼리셋의 필드와 데이터 유형이 서로 일치할 때만 실행할 수 있음
  • values_list()를 이용해 공통된 필드만 가져온 뒤 union을 수행할 수 있음
>>> q1 = User.objects.filter(id__gte=5)
>>> q1

<QuerySet [<User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>

>>> q2 = User.objects.filter(id__lte=9)
>>> q2

<QuerySet [<User: yash>, <User: John>, <User: Ricky>, <User: sharukh>, <User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>]>


# 합하려는 쿼리셋의 모델이 서로 다른 경우, 각 쿼리셋에 포함된 필드와 데이터 유형이 서로 맞아야 함
>>> q1.union(q2)

<QuerySet [<User: yash>, <User: John>, <User: Ricky>, <User: sharukh>, <User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>

>>> q2.union(q1)

<QuerySet [<User: yash>, <User: John>, <User: Ricky>, <User: sharukh>, <User: Ritesh>, <User: Billy>, <User: Radha>, <User: sohan>, <User: Raghu>, <User: rishab>]>


# union 메서드는 합하려는 쿼리셋의 필드와 데이터 유형이 서로 일치할 때만 실행할 수 있음
>>> q3 = EventVillain.objects.all()
>>> q3

<QuerySet [<EventVillain: EventVillain object (1)>]>

>>> q1.union(q3) # 오류 발생

django.db.utils.OperationalError: SELECTs to the left and right of UNION do not have the same number of result columns


# values_list()를 이용해 공통된 필드만 가져온 뒤 union을 수행할 수 있음

Hero.objects.all().values_list("name", "gender")
	    .union(Villain.objects.all().values_list("name", "gender"))

필요한 열만 골라서 조회

  • 필드가 전부 다 필요하지 않을 때, 필요한 열만을 데이터베이스에서 읽어오는 방법
    • 쿼리셋의 values() 메서드와 values_list() 메서드
    • only 메서드
# 조건의 SQL 질의문
SELECT "auth_user"."first_name", "auth_user"."last_name"
FROM "auth_user" WHERE "auth_user"."first_name"::text LIKE R%


>>> User.objects.filter(first_name__startswith='R')
	        .values('first_name', 'last_name')

<QuerySet [{'first_name': 'Ricky', 'last_name': 'Dayal'}, {'first_name': 'Ritesh', 'last_name': 'Deshmukh'}, {'first_name': 'Radha', 'last_name': 'George'}, {'first_name': 'Raghu', 'last_name': 'Khan'}, {'first_name': 'Rishabh', 'last_name': 'Deol'}]


>> queryset = User.objects.filter(first_name__startswith='R')
			  .only("first_name", "last_name")
>>> str(queryset.query)

SELECT "auth_user"."id", "auth_user"."first_name", "auth_user"."last_name"
FROM "auth_user" WHERE "auth_user"."first_name"::text LIKE R%
profile
🌱 Backend-Dev | hwaya2828@gmail.com

0개의 댓글