본문 바로가기
관리자

Programming-[Backend]/Django

[TIL] Django ORM values, annotate, Subquery, OuterRef, JSONField, Type Cast 부분 적용

728x90
반응형

 

자세한 내용은 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)
  • --> 정상 작동
728x90
반응형