Django에서 다중 필터 제작이 필요하였다. 기본조건은 두가지였다.
- 카테고리가 필요하다
- 검색 기능이 필요하다
추가적으로
contains
의 경우 list
형태로서의 검색이 (내가 간단히 찾아본 바로는) 불가능하다. functools
의 reduce
를 사용하여 추가적인 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 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 %}
추가적으로, Django에선 특정 app 하나에만 template tag가 등록되면 같은 프로젝트내 어떤앱의 template에서든
load
가 가능하다.