Я работаю над ListView
, который включает в себя две формы, форму поиска и форму фильтра. Обе формы в конечном итоге изменяют представление queryset
с помощью его метода get_queryset
. Я хотел бы сделать так, чтобы при поиске чего-то фильтры сохранялись, и наоборот.
Это более или менее работает, но есть еще одна ошибка: всякий раз, когда я что-то ищу, появляется кнопка «CLEAR FILTERS», которой там быть не должно:
В шаблоне форма поиска включена примерно так:
{% block search_form %}
{% with action='dashboard:families' placeholder='Search Families' %}
{% include '_search.html' %}
{% endwith %}
{% endblock %}
, где _search.html
-
{% load get %}
<form action="{% url action %}" method="get" class="left search col s6 hide-on-small-and-down" novalidate>
<div class="input-field">
<input id="search" placeholder="{{ placeholder }}"
autocomplete="off" type="search" name="q"
value="{{ search_form.q.value.strip|default:'' }}"
data-query="{{ search_form.q.value.strip|default:'' }}">
<label for="search" class="active"><i class="material-icons search-icon">search</i></label>
<i data-behavior="search-clear"
class="material-icons search-icon"
{% if not search_form.q.value %}style="display: none;"{% endif %}>close</i>
</div>
{% if filter_form %}
{% for field in filter_form %}
<input type="hidden" name="{{ field.name }}" value="{{ request.GET|get:field.name }}"/>
{% endfor %}
{% endif %}
</form>
и пользовательский фильтр get
просто реализует метод dict.get
:
from django import template
register = template.Library()
@register.filter
def get(dictionary, key):
return dictionary.get(key)
Короче говоря, форма поиска содержит скрытый filter_form
, который отправляется с поисковым запросом.
Часть шаблона, которая содержит форму фильтра, выглядит следующим образом:
<form action={% url 'dashboard:families' %} method="GET" data-behavior="filters">
<input type="hidden" name="q" value="{{ request.GET.q.strip }}"/>
<div class="input-field col s2">
{{ filter_form.guide }}
<label class="active">Guide</label>
{% if filter_form.is_guide_filled %}
<a href="" class="clear"><i class="material-icons tiny">clear</i></a>
{% endif %}
</div>
<div class="input-field col s2">
{{ filter_form.status }}
<label class="active">Status</label>
{% if filter_form.is_status_filled %}
<a href="" class="clear"><i class="material-icons">clear</i></a>
{% endif %}
</div>
<div class="input-field col s2">
{{ filter_form.package }}
<label class="active">Company / Package</label>
{% if filter_form.is_package_filled %}
<a href="" class="clear"><i class="material-icons tiny">clear</i></a>
{% endif %}
</div>
<div class="input-field col s2">
{{ filter_form.next_outreach }}
<label>Outreach</label>
{% if filter_form.is_next_outreach_filled %}
<a href="" class="clear"><i class="material-icons tiny">clear</i></a>
{% endif %}
</div>
<div class="input-field col s2">
{{ filter_form.country }}
<label class="active">Country</label>
{% if filter_form.is_country_filled %}
<a href="" class="clear"><i class="material-icons tiny">clear</i></a>
{% endif %}
</div>
<div class="input-field col s1">
{{ filter_form.vip }}
<label>VIP</label>
{% if filter_form.is_vip_filled %}
<a href="" class="clear"><i class="material-icons tiny">clear</i></a>
{% endif %}
</div>
<div class="input-field col s1">
{{ filter_form.app }}
<label>App</label>
{% if filter_form.is_app_filled %}
<a href="" class="clear"><i class="material-icons tiny">clear</i></a>
{% endif %}
</div>
<a href="{% url 'dashboard:families' %}?q={{ request.GET.q.strip }}"
data-behavior="clear-filters"
class="btn-flat" {% if not filter_form.is_filled %}style="display: none;"{% endif %}>
<i class="material-icons">close</i>Clear Filters
</a>
</form>
Обратите внимание, что форма фильтра также содержит скрытое поле с именем q
с поисковым запросом. Поскольку это CharField
, имеет смысл установить value
как request.GET.q.strip
.
Проблема в том, что если я попаду в отладчик в FamilyFilterForm
, я вижу, что данные формы являются «строковой» версией того, что я ожидаю:
ipdb> self.data
<QueryDict: {'q': ['Christine'], 'status': ['None'], 'next_outreach': [''], 'country': ['None'], 'vip': [''], 'app': [''], 'guide': ['6'], 'package': ['None']}>
Обратите внимание, как значение None
было преобразовано в строку 'None'
. Это заставляет свойство is_filled
формы фильтра «думать», что значение было заполнено, тогда как на самом деле это не так.
Вместо этого я хотел бы, чтобы данные формы были эквивалентны
ipdb> from django.http import QueryDict
ipdb> query_dict = QueryDict('q=Christine&guide=6')
ipdb> query_dict.dict()
{'q': 'Christine', 'guide': '6'}
и, в частности, если фильтры не применяются, это должен быть пустой QueryDict()
или {}
.
Как я могу избежать 'stringified' значений request.GET
при передаче как value
в шаблоне таким способом?