ORM cookbook 4

sharosoo·2022년 5월 3일
0

ORMcookbook

목록 보기
4/5
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rest.settings')
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
django.setup()
from django.contrib.auth import get_user_model
from django.db.models import Q
from events.models import *
from entities.models import *
User = get_user_model()

10. JOIN

  • 동일한 값을 가진 column을 기준으로 두 표를 결합할 수 있다.
  • select_related는 정방향 참조 모델에 대해서 Join한다.
queryset = Article.objects.select_related('reporter').values(
    'headline',
    'reporter__username'
)

SQL_query = str(queryset.query)
print(SQL_query)
SELECT "events_article"."headline", "auth_user"."username" 
FROM "events_article" 
INNER JOIN "auth_user" 
ON ("events_article"."reporter_id" = "auth_user"."id") 
ORDER BY "events_article"."headline" ASC
  • ORM은 똑똑해서 select_related를 포함하지 않더라도 필요에 따라 알아서 JOIN해주는 경우가 있다.
    • 정방향 참조 모델의 필드를 filter하거나 필드로 포함시켜야 하는 경우가 그렇다.
  • 위의 쿼리에서 select_related를 명시하지 않더라도 똑같이 작동한다.
queryset = Article.objects.values(
    'headline',
    'reporter__username'
)

SQL_query = str(queryset.query)
print(SQL_query)
SELECT "events_article"."headline", "auth_user"."username" 
FROM "events_article" 
INNER JOIN "auth_user" 
ON ("events_article"."reporter_id" = "auth_user"."id") 
ORDER BY "events_article"."headline" ASC
  • 그런데 ORDER BY를 언급하지 않았는데 쿼리에 들어가는 건 참 이상하다.
    - https://docs.djangoproject.com/en/3.2/ref/models/querysets/#order-by
    • ORDER BY를 빼고 싶다면 order_by()를 사용하면 된다.
    • 순서가 상관 없는 경우에는 명시적으로 order_by()를 포함시켜주는 것이 좋을 것 같다.

11. N번째로 큰 항목?

  • django ORM에서 첫번째 항목은 first(), 마지막 항목은 last()메서드로 구할 수 있다.
  • 그러나 N번째 항목을 구하는 메서드는 따로 제공되지 않기 때문에, 파이썬의 인덱싱 연산을 이용해야 한다.
# 2번째 항목
user = User.objects.order_by('-last_login')[1]
user.first_name
'Ritesh'
# n번째 항목
user = User.objects.order_by('-last_login')[n-1]
  • 내부적으로 n번째 항목까지 LIMIT와 OFFSET을 걸어 필요한 항목만 가져온다.
  • 다음의 구조와 같다.
n = 10
offset = n-1
queryset = User.objects.values('username').order_by('-last_login')[offset:n]
print(str(queryset.query))
SELECT "auth_user"."username" 
FROM "auth_user" 
ORDER BY "auth_user"."last_login" DESC 
LIMIT 1 OFFSET 9

12. Count - column값이 중복인 데이터 찾기

  • 특정 column이 중복인 data를 구하는 방법에는 여러가지가 있다.
  • Count를 이용해 2번 이상 나타나는 value를 구하고 column이 value인 데이터를 query할 수 있다.
from django.db.models import Count
# 중복인 column값들 구하기
duplicates = User.objects.values(
    'first_name'
).annotate(
    name_count=Count('first_name')
).filter(
    name_count__gt=1
)

print(str(duplicates.query))
SELECT "auth_user"."first_name", 
COUNT("auth_user"."first_name") AS "name_count" 
FROM "auth_user" 
GROUP BY "auth_user"."first_name" 
HAVING COUNT("auth_user"."first_name") > 1
# 중복인 column값을 가지는 data 구하기
records = User.objects.filter(
    first_name__in=[item['first_name'] for item in duplicates]
)

13. Count - 고유한 필드 값을 가진 데이터 찾기

  • 위의 예제와 비슷하다
# 고유한 필드값을 가지는 경우
uniques = User.objects.values(
    'first_name'
).annotate(
    name_count=Count('first_name')
).filter(
    name_count=1
)

print(str(uniques.query))
SELECT "auth_user"."first_name", 
COUNT("auth_user"."first_name") AS "name_count" 
FROM "auth_user" 
GROUP BY "auth_user"."first_name" 
HAVING COUNT("auth_user"."first_name") = 1
# 고유한 필드값을 가지는 data 구하기
records = User.objects.filter(
    first_name__in=[item['first_name'] for item in uniques]
)
profile
🐾

0개의 댓글