Виджет SelectMultiple

Виджет SelectMultiple в Django представляет собой виджет формы, который отображается как HTML-элемент <select multiple>. Он позволяет пользователю выбирать один или несколько вариантов из предложенного списка. Данный виджет используется вместе с полями формы, которые поддерживают множественный выбор, такими как MultipleChoiceField, TypedMultipleChoiceField и ModelMultipleChoiceField. Виджет автоматически обрабатывает передачу выбранных значений от клиента к серверу.

Синтаксис

pythonfrom django import forms

class MyForm(forms.Form):
  field_name = forms.MultipleChoiceField(
    choices=CHOICES_TUPLE,
    widget=forms.SelectMultiple(attrs={'class': 'my-class', 'size': 5})
  )

Пример . С ChoiceField

Рассмотрим пример использования виджета SelectMultiple с полем MultipleChoiceField для выбора любимых языков программирования:

pythonfrom django import forms

LANGUAGE_CHOICES = [
  ('python', 'Python'),
  ('javascript', 'JavaScript'),
  ('java', 'Java'),
  ('csharp', 'C#'),
  ('go', 'Go'),
]

class LanguageForm(forms.Form):
  favorite_languages = forms.MultipleChoiceField(
    choices=LANGUAGE_CHOICES,
    widget=forms.SelectMultiple(attrs={'class': 'lang-select'})
  )

Созданная форма будет отображать выпадающий список, в котором пользователь может выбрать несколько языков, удерживая клавишу Ctrl (или Cmd на macOS).

Пример . С ModelChoiceField

Виджет SelectMultiple часто используется для связей ManyToManyField. Рассмотрим пример с моделью и формой на основе модели:

pythonfrom django.db import models
from django import forms

class Tag(models.Model):
  name = models.CharField(max_length=50)

  def __str__(self):
    return self.name

class Article(models.Model):
  title = models.CharField(max_length=200)
  tags = models.ManyToManyField(Tag)

class ArticleForm(forms.ModelForm):
  class Meta:
    model = Article
    fields = ['title', 'tags']
    widgets = {
      'tags': forms.SelectMultiple(attrs={'size': 6}),
    }

В этом примере виджет SelectMultiple используется для поля tags. Атрибут size=6 задаёт количество отображаемых вариантов без прокрутки. В форме будет отображаться список всех существующих тегов, из которых можно выбрать несколько.

Атрибуты виджета

Виджет SelectMultiple принимает стандартные атрибуты HTML через параметр attrs. Наиболее полезные атрибуты:

pythonfrom django import forms

class MyForm(forms.Form):
  choices = forms.MultipleChoiceField(
    choices=[(1, 'Option 1'), (2, 'Option 2'), (3, 'Option 3')],
    widget=forms.SelectMultiple(attrs={
      'class': 'my-select',
      'id': 'my-select-id',
      'size': 4,
      'style': 'width: 200px;',
    })
  )

Атрибут size определяет высоту списка в строках. Атрибуты class и id используются для стилизации и JavaScript-манипуляций.

Получение выбранных значений

После отправки формы выбранные значения можно получить из свойства cleaned_data. Для полей с множественным выбором это будет список значений:

pythonfrom django import forms

class LanguageForm(forms.Form):
  favorite_languages = forms.MultipleChoiceField(
    choices=[
      ('python', 'Python'),
      ('javascript', 'JavaScript'),
      ('java', 'Java'),
    ],
    widget=forms.SelectMultiple
  )

# В представлении:
form = LanguageForm(request.POST)
if form.is_valid():
  selected = form.cleaned_data['favorite_languages']
  print(selected)  # ['python', 'java']

Результат выполнения кода:

python"['python', 'java']"

Начальное значение

Для виджета SelectMultiple начальные значения можно задать с помощью параметра initial в поле формы. Передайте список предварительно выбранных значений:

pythonfrom django import forms

class LanguageForm(forms.Form):
  favorite_languages = forms.MultipleChoiceField(
    choices=[
      ('python', 'Python'),
      ('javascript', 'JavaScript'),
      ('java', 'Java'),
      ('go', 'Go'),
    ],
    widget=forms.SelectMultiple,
    initial=['python', 'go']
  )

При отображении формы варианты "Python" и "Go" будут предварительно выделены.

Обработка обязательности

По умолчанию поле MultipleChoiceField обязательное (required=True). Если необходимо разрешить пользователю не выбирать ни одного варианта, установите параметр required=False:

pythonfrom django import forms

class OptionalSelectForm(forms.Form):
  languages = forms.MultipleChoiceField(
    choices=[('python', 'Python'), ('java', 'Java')],
    widget=forms.SelectMultiple,
    required=False
  )

Если пользователь не выберет ни одного значения, поле вернёт пустой список [] в cleaned_data.

Смотрите также

  • виджет CheckboxSelectMultiple,
    который отображает варианты выбора в виде флажков
  • поле формы ModelMultipleChoiceField,
    которое работает с множественным выбором из модели
  • виджет Select,
    который предназначен для одиночного выбора
  • поле формы MultipleChoiceField,
    которое поддерживает множественный выбор