Виджет NullBooleanSelect

Виджет NullBooleanSelect применяется к полю формы NullBooleanField и представляет собой выпадающий список (select) с тремя опциями: "Unknown" (значение None), "Yes" (значение True) и "No" (значение False). Этот виджет используется, когда необходимо предоставить пользователю возможность выбора между тремя состояниями: утвердительным, отрицательным и неопределенным. По умолчанию NullBooleanSelect используется для поля NullBooleanField в формах Django.

Синтаксис

pythonfrom django import forms

class MyForm(forms.Form):
  field_name = forms.NullBooleanField(
    widget=forms.NullBooleanSelect(attrs={'class': 'my-class'})
  )

Виджет принимает необязательный параметр attrs для передачи HTML-атрибутов элемента select.

Пример

Давайте создадим форму с полем для выбора статуса согласия пользователя:

pythonfrom django import forms

class ConsentForm(forms.Form):
  agree = forms.NullBooleanField(
    label="Are you agree?",
    widget=forms.NullBooleanSelect(attrs={'class': 'form-select'})
  )
  
  def clean_agree(self):
    agree = self.cleaned_data.get('agree')
    if agree is None:
      raise forms.ValidationError("Please make a choice.")
    return agree

Теперь создадим экземпляр формы и отобразим поле в шаблоне:

pythonfrom django.shortcuts import render
from .forms import ConsentForm

def consent_view(request):
  form = ConsentForm()
  return render(request, 'consent.html', {'form': form})

В шаблоне вы можете отобразить поле следующим образом:

ninja<form method="post">
  {% csrf_token %}
  {{ form.agree }}
  <button type="submit">Submit</button>
</form>

Результат в HTML будет выглядеть так:

html<select name="agree" class="form-select">
  <option value="1">Unknown</option>
  <option value="2">Yes</option>
  <option value="3">No</option>
</select>

Пример

Давайте обработаем отправленные данные формы с использованием NullBooleanSelect:

pythonfrom django import forms
from django.shortcuts import render
from django.http import HttpResponse

class SubscriptionForm(forms.Form):
  subscribe = forms.NullBooleanField(
    label="Subscribe to newsletter?",
    widget=forms.NullBooleanSelect
  )

def subscription_view(request):
  if request.method == 'POST':
    form = SubscriptionForm(request.POST)
    if form.is_valid():
      subscribe = form.cleaned_data['subscribe']
      if subscribe is True:
        return HttpResponse("Subscription confirmed.")
      elif subscribe is False:
        return HttpResponse("Subscription declined.")
      else:
        return HttpResponse("No decision made.")
  else:
    form = SubscriptionForm()
  return render(request, 'subscription.html', {'form': form})

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

python# Если выбрано "Yes" (значение 2):
"Subscription confirmed."

# Если выбрано "No" (значение 3):
"Subscription declined."

# Если выбрано "Unknown" (значение 1):
"No decision made."

Пример

Давайте используем виджет с моделью через ModelForm для поля, допускающего значение None:

pythonfrom django.db import models
from django import forms

class UserProfile(models.Model):
  user = models.OneToOneField('auth.User', on_delete=models.CASCADE)
  receive_emails = models.BooleanField(null=True, blank=True)

class ProfileForm(forms.ModelForm):
  class Meta:
    model = UserProfile
    fields = ['receive_emails']
    widgets = {
      'receive_emails': forms.NullBooleanSelect(
        attrs={'class': 'form-control'}
      ),
    }

# Создаем форму с существующим экземпляром
profile = UserProfile.objects.get(id=1)
form = ProfileForm(instance=profile)

# Выводим HTML виджета
print(form['receive_emails'].as_widget())

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

html<select name="receive_emails" class="form-control">
  <option value="1">Unknown</option>
  <option value="2" selected>Yes</option>
  <option value="3">No</option>
</select>

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

  • виджет CheckboxInput,
    который используется для полей с двумя состояниями
  • виджет Select,
    который создает стандартный выпадающий список
  • виджет RadioSelect,
    который отображает выбор в виде радиокнопок
  • поле BooleanField,
    которое предназначено для булевых значений