Отправка двух форм одновременно в Джанго - PullRequest
0 голосов
/ 09 мая 2018

Я работаю над ListView, который включает в себя две формы, форму поиска и форму фильтра. Обе формы в конечном итоге изменяют представление queryset с помощью его метода get_queryset. Я хотел бы сделать так, чтобы при поиске чего-то фильтры сохранялись, и наоборот.

Это более или менее работает, но есть еще одна ошибка: всякий раз, когда я что-то ищу, появляется кнопка «CLEAR FILTERS», которой там быть не должно:

enter image description here

В шаблоне форма поиска включена примерно так:

{% 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 в шаблоне таким способом?

1 Ответ

0 голосов
/ 14 мая 2018

Мне удалось правильно включить скрытое filter_form (с правильно представленными полями с несколькими вариантами выбора) с помощью свойства поля as_hidden. Таким образом, шаблон _search.html становится

<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>
  {% for field in filter_form %}
    {{ field.as_hidden }}
  {% endfor %}
</form>

Аналогично, форма фильтра содержит

{{ search_form.q.as_hidden }}

для сохранения поисковых запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...