자세한 내용은 Django 공식 문서에 있다. 여기서는 기존 다른 SQL에서 자주 사용하는 기능들을 한 눈에 대략적으로 파악할 수 있도록만 정리한다.
Django 공식 문서 - Queryset
https://docs.djangoproject.com/en/4.1/ref/models/querysets/
코드
User.objects
.annotate(
user_name=F("name"),
comment_file_path=Subquery(
Comment.objects.annotate(file_path=F("data__file_path"))
.values("data__file_path")
.filter(user=OuterRef("pk"))[:1]
),
)
.values("user_name", "comment_file_path")
.filter(
...
)
모델
- User:Comment = 1:N
- Comment에는 data 라는 Column이 있어서 Json으로 값을 넣을 수 있다. ex) comment.data = {'file_path': '/aws/test_storage/file.txt'}
문법
User 테이블에 있는 name값과 Comment 테이블에 있는 data.file_path 값을 얻어오고 싶은 상황이다.
annotate
alias를 지정한다. user_name=F("name")으로 User 테이블의 "name" 컬럼값을 user_name 이라는 이름으로 지정해서 가져온다.
Subquery
서브 쿼리를 지정해줄 수 있다.
values
어떤 모델에서 가져올 값을 컬럼 이름을 입력해서 지정한다.
data__file_path
django에서 JSONField 내부의 값을 가져올 수 있는 문법이다. JSON의 depth 마다 underbar(_)를 2개씩 써주면 된다. postgres에서는 data -> 'file_path' 로 작동한다. 이렇게 가져온 값은 jsonb 타입이 된다.
OuterRef
Subquery에서 외부 모델을 지정할 때 사용한다. 위 코드에서는 Comment 모델에서 가지고 있는 user의 user_id값을 User.pk로 매칭하여 .filter를 적용했다.
[:1]
python 문법을 그대로 사용한다. limit 1 을 걸어준다.
추가 문제: filter 조건문이 JSONField인 경우 - Cast Function (답 못찾음)
만약 아래와 같이 filter의 조건문의 좌항이 JSONField를 지칭하는 구문이면 좌항의 타입이 jsonb가 되어 우항과 타입이 맞지 않아서 비교가 되질 않는다.
- Django ORM 문법 : .filter(data__file_path="/temp/files/test.txt")
- postgres 문법 : WHEN data -> 'file_path' = "/temp/files/test.txt"
이 때 사용할 수 있는 것이 Cast Function 인데, 좀 찾아봤으나 좌항 자체를 Cast 할 수 있는 방법은 없는 것 같다... postgres에서는 잘 먹힌다..
from django.models import TextField
- Django ORM 문법 : .filter(Cast(data__file_path, models.TextField())=Cast("/temp/files/test.txt", models.TextField())
- --> 우항의 Cast는 작동하나, 좌항의 조건에 대한 Cast는 적용 불가..
- postgres 문법 : WHEN Cast(data -> 'file_path' as text) = Cast("/temp/files/test.txt" as text)
- --> 정상 작동
'Programming-[Backend] > Django' 카테고리의 다른 글
[TIL] Django prefetch_related, Prefetch 2depth, 모델 필드 정보 조회 (0) | 2022.12.07 |
---|---|
[TIL] django.conf settings, 환경 설정 정보 상대 참조하기 (0) | 2022.11.02 |
[TIL] 부모 Serializer field 값 제거 (0) | 2022.09.29 |
[TIL] Django created_by, modified_by 적용하기 : django crum, settings.AUTH_USER_MODEL 등 (0) | 2022.09.28 |
[TIL] Django ModelSerializer의 field, validate()의 data (0) | 2022.09.21 |