I\'m working on a Django project with a ListView
that has both a search form, known in the view\'s context as search_form
, and a filter form, fil
I finally solved this by writing a custom get
filter as described in Django template how to look up a dictionary value with a variable:
from django import template
register = template.Library()
@register.filter
def get(dictionary, key):
return dictionary.get(key)
I updated _search.html
as follows:
{% 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>
Now, if I try to search a filtered result, it works as expected:
Note that this also works fine for the filters that are not applied - these have the value None
instead of an empty string - without any need to filter them out in the form.
So it basically boils down to not submitting keys in the GET request that have an empty string value. This appears to be unsupported natively in HTML; you need some JS magic to make this happen. See this thread: How to prevent submitting the HTML form's input field value if it empty
However, a pure Django solution would be to modify your filter dict to exclude keys that are null. I am not sure how you are filtering this in Django, but assuming you have override the get_queryset
method; you can always do:
def get_queryset(self):
qs = super(YourView, self).get_queryset()
filters = {k, v for k, v in request.GET.items() if v != ''} # Be as generic/specific as needed here for exclusion
qs = qs.filter(**filters) # Fire your filtering logic here; this is a sample
return qs