Форма множественного выбора в форме расширенного поиска

Я пытаюсь создать форму множественного выбора, в которой можно выбрать любую комбинацию языков. Это находится в поле формы поиска:

class AdvancedSearchForm(SearchForm):
    terms_show_partial_matches = forms.BooleanField(required=False,
        label=_("Show partial matches in terms")
    )
    definitions_show_partial_matches = forms.BooleanField(required=False,
        label=_("Show partial matches in definitions")
    )
    case_sensitive = forms.BooleanField(required=False,
        label=_("Case sensitive")
    )
...

Я хотел бы реализовать что-то вроде этого:

filter_by_part_of_speech = forms.ModelChoiceField(
    queryset=PartOfSpeech.objects.all(), required=False,
    label=_("Filter by part of speech")
)

Однако это должно быть поле множественного выбора, чтобы можно было выбрать любое из значений. В идеале мне нужна форма, в которой флажки уже отмечены. То есть что-то вроде этого:

LANG_CHOICES = (
    ("1", "lang1"),
    ("2", "lang2"),
    ("3", "lang3"),
    ("4", "lang4"),
)
filter_by_language = forms.MultipleChoiceField(choices=Language.objects.all().filter(name__in=LANG_CHOICES).values(), required=False, label=_("Filter by language"))

Фильтр вызывается из представления примерно так:

tqs = tqs.filter(language=language_filter)

Теперь, хотя поиск работает нормально, значения не отображаются. С другой стороны, они отображаются, если я заполню список и просто напишу:

choices=list(lang_list)

Но тогда, очевидно, поиск фактически не выполняется.

Итак, мои вопросы следующие:

  • Можно ли адаптировать конструктор для корректного отображения значений?
  • Следует ли мне реализовать фильтр в представлении? Если да, то как?
  • Использую ли я правильный тип формы или есть лучшие варианты, такие как предоставление списка флажков, которые установлены по умолчанию?

Я использую Django 2.2 (планирую скоро обновить) на данный момент.

Файл шаблона просто ссылается на def поиска в представлении, который вызывает форму расширенного поиска и другие:

{% block breadcrumbs_item %}<a href="{% url "advanced_search" %}">{% trans "Advanced Search" %}</a>{% endblock %}

Не очень уместно, я думаю, но вот модель языка:

class Language(models.Model):
    iso_code = models.CharField(primary_key=True, max_length=10, verbose_name=_("ISO code"))
    name = models.CharField(max_length=50, verbose_name=_("name"))
    description = models.TextField(verbose_name=_("description"), null=True, blank=True)

    class Meta:
    verbose_name = _("language")
    verbose_name_plural = _("languages")

    def __str__(self):
        return _("%(language_name)s (%(iso_code)s)") % {'language_name': self.name, 'iso_code': self.iso_code}

Я бы использовал что-то вроде CheckBoxSelectMultiple в форме: (отказ от ответственности, я не знаю, поддерживается ли это в том виде, в котором это написано в django 2.2)

filter_by_language = forms.ModelMultipleChoiceField(required=True,
       queryset=Language.objects.all().filter(name__in=LANG_CHOICES).values(),
        widget=forms.CheckboxSelectMultiple)

И есть много постов в стеке о том, как сделать начальные значения проверяемыми, например, этот.

Кроме того, если у вас в итоге получится длинный список флажков (вероятный сценарий при использовании этого виджета), вы можете стилизовать их в колонки для улучшения UX, например, так:

<style>
    .my-language-checkboxes {
        column-width: 25%;
        column-count: 4;
        column-fill: balance;
    }
</style>

<div id="my-language-checkboxes">
{{ form.filter_by_language }}
</div>

Что касается представления, я сделаю предположение, что вы знаете, как написать базовое представление, и вам нужен именно метод сохранения. В таком случае вам понадобится что-то вроде:

         if request.method == 'POST:
            if form.is_valid():
                form.save_m2m()

Это также предполагает, что вы связываете языки с родительским объектом через ManyToManyField, что является обычным сценарием.

Вернуться на верх