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
11. N번째로 큰 항목?
- django ORM에서 첫번째 항목은
first()
, 마지막 항목은 last()
메서드로 구할 수 있다.
- 그러나 N번째 항목을 구하는 메서드는 따로 제공되지 않기 때문에, 파이썬의 인덱싱 연산을 이용해야 한다.
user = User.objects.order_by('-last_login')[1]
user.first_name
'Ritesh'
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
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
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
records = User.objects.filter(
first_name__in=[item['first_name'] for item in uniques]
)