Форма множественного выбора в форме расширенного поиска
Я пытаюсь создать форму множественного выбора, в которой можно выбрать любую комбинацию языков. Это находится в поле формы поиска:
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, что является обычным сценарием.