python Back-End 개발을 시작한지 얼마되지 않아,
소스 내 ORM 코드 개선 작업을 하게되었다.
기존 코드는 execute() 의 파라미터에 DB쿼리의 문자열 변수로 select 조회하는 방식이였는데,
이전 직장에서 .Core 환경에서의 EF(Entity Framework) 코드 짜던 버릇으로
개선하기로 마음먹고 수정작업을 진행했었는데, 그 중 시행착오를 겪었던 부분을 이렇게 블로그에 남기면 좋을 것 같아 글을 게시해본다.
일단 내가 원하는 sql query 문과 swagger GET api 호출 결과는 아래와 같다.
select 1111 as 'seq',
avg(or.result_values[1]) * 100 as 'positive'
avg(or.result_values[2]) * 100 as 'negative'
avg(or.result_values[3]) * 100 as 'nomal'
from obaervation_info as oi
join observation_result as or on oi.id = or.observation_info_id
where oi.seq = 1111
and or.observation_time > 600
and or.isValidDataRow = 1
{
"seq":1111,
"positive":null,
"negative":null,
"nomal":null
}
시행착오는 겪었던 부분은 바로 맨 윗부분이다.
select 1111 as 'seq',
1111 은 함수호출시의 인자 값이다.
아래 코드는 해결되기 전의 기존 python ORM 코드이다.
def get_observiation_no_result(no):
try:
return db.session.query(
ObservationInfo.seq.label('seq'),
(func.avg(ObservationResult.result_value[1])*100).label('positive'),
(func.avg(ObservationResult.result_value[1])*100).label('positive'))\
.select_from(ObservationInfo)
.join(ObservationResult, ObservationInfo.id == ObservationResult.observation_info_id)\
.filter(
and_(oi.seq == no,
or.observation_time > 600
or.isValidDataRow = 1)
).first()
exception Exception as e:
print(e)
finally:
db.session.close()
위의 코드에서 문제점은 조건절에 조회되는 데이타가 없을 경우
원하는 json 결과로 리턴되지 않는다는 것이다.
(http Status Code 204 로 리턴)
따라서 조건절에 조회되는 데이타가 없더라도
'seq' 에는 인자값이 들어간 리턴을 받고 싶기때문에 해결책으로 cast() 를 활용하는 방법을 생각했다.
def get_observiation_no_result(no):
try:
...
func.cast(no, Integer).label('seq'),
...
finally:
db.session.close()
포스팅이 처음이라 읽기 난잡할 수 있을 것 같은데,
비슷한 고민을 하는 개발자에게 힌트가 되었으면 한다.
만약 더 좋은 해결책이 있으면 공유받았으면 좋겠다.