Django: Magic Q Query
Django: Magic Q Query

Django: Magic Q Query

Published
February 8, 2023
Author
WonJung Kim
Django에서 다중 필터 제작이 필요하였다. 기본조건은 두가지였다.
  1. 카테고리가 필요하다
  1. 검색 기능이 필요하다
 
Velog의 한 글에서 방법을 찾았다. 빈 Q() 쿼리는 All 조건이라는것을 알수 있었으며, 연산자를 사용하여 Optional한 조건문의 구현이 가능하였다.
추가적으로 contains 의 경우 list 형태로서의 검색이 (내가 간단히 찾아본 바로는) 불가능하다. functoolsreduce를 사용하여 추가적인 or 연산을 구현해봤다.
from django.db.models import Q from functools import reduce from .models import Model def view(request): contains = request.GET.get('contains', None) category = request.GET.get('category', None) q = Q() if contains: q &= reduce(operator.or_, ( Q(name__contains=x) for x in contains.split() ) ) if category: q &= Q(category__name = category) model = Model.objects.filter(q).order_by('created_at')
다중 필터 Query 구현 예제
 
이에 대한 Query parameter를 만들어야 했다. Template 안에서 만들어야 했기 때문에 자체 template function을 먼저 찾아봤으나 Django 자체적으로는 지원하지 않았다.
Stack Overflow에서 Django의 template tag 시스템을 이용해 자체적으로 구현한 내용을 찾았다.
# app/templatetags/urlparams.py from django import template from urllib.parse import urlencode register = template.Library() @register.simple_tag def urlparams(*_, **kwargs): safe_args = {k: v for k, v in kwargs.items() if v is not None} return '?{}'.format(urlencode(safe_args)) if safe_args else ''
urlparams template tag 구현 예제
{% load urlparams %} {% for category in category_list %} <a href="{% url 'app:view' &}{% urlparams page=page_obj.number category=category %}">{{ category }}</a> {% endfor %}
Template 안에서의 사용법 예제
추가적으로, Django에선 특정 app 하나에만 template tag가 등록되면 같은 프로젝트내 어떤앱의 template에서든 load가 가능하다.
 

References