Development/Django

Django Model 동적 Filtering

Ahn Paul 2019. 8. 7. 00:01

장고의 ORM으로 개발을 하다보면 동적으로 모델을 필터링 해야 하는 경우가 생길 수 있습니다.

 

예를 들어, 데이터 필드가 성별, 연령대(10대, 20대··)가 있다고 가정할 때 각각 필드에 대해서 한 가지의 조건만 준다면 사실상 Q나 동적인 필터링을 사용할 이유가 없습니다. 단순히 Model.objects.filter(성별='남자')와 같이 처리할 수 있기 때문입니다.

 

그러나, 만약에 연령대가 10대, 30대이고, 성별이 여자인 사람을 뽑아내고 싶다면 위의 방법으로는 불가능합니다. 따라서 이때 사용하는 함수가 Q입니다. Model.objects.filter((Q(연령대='10대')|Q(연령대='30대')), 성별="여자")와 같이 처리할 수 있습니다.

 

여기서 만족하지 않고, 클라이언트로부터 받아온 데이터들을 동적으로 필터링을 하고 싶을 때는 위의 방법이 사실상 불가능합니다. 즉, 클라이언트에서 [10대, 30대, 남자]의 데이터를 받아서 필터링을 해야 한다면 위의 방법도 불가능합니다.

 

이때 위를 해결하기 위해서는 각각 값에 해당하는 Q를 리스트에 Appending하고 operator와 reduce를 사용하여 해결할 수 있습니다.

 


def dynamicFiltering(){ 
    from operator    
    from functools import reduce        
    list_ = []
    for val in datasets:        
    	list_.append(Q(field=val))  // 리스트에 Q 객체를 추가합니다.       
    Model.objects.filter(reduce(operator.or_, list_)) // Q 객체가 있는 Iterator 이용해 필터
    					링을 할 수 있습니다. and_를 통해 and 연산도 가능합니다.}

 


reduce(operator.or_, list_)의 역할은 간단하게 list_의 Iterator를 operator.or_ ( | ) 연산을 처리하는 거라고 생각하시면 됩니다. list_에 A, B, C가 있다면 (Q(field=A)|Q(field=B)|Q(field=C))가 반환됩니다.