Django: как изменить значения для nullbooleanfield в модели?

В документах представлен nullbooleanfield as a <select> box with "Unknown", "Yes" and "No" choices.. Как изменить значения select на некоторые другие более значимые тексты и сопоставить их с да, нет и неизвестными значениями в моем modelform?

Например, у меня есть yes_no_required = models.NullBooleanField(), и я хотел бы иметь сопоставление 'yes I acknowledge this', 'no, I do not like this' и 'I do not know now' в yes, no и required соответственно.

Ответы

Ответ 1

Я потратил полчаса на демонстрацию, чтобы доказать, что это работает:

CHOICES = (
    (None, "I do not know now"),
    (True, "Yes I acknowledge this"),
    (False, "No, I do not like this")
)

class Demo(models.Model):
    yes_no_required = models.NullBooleanField(choices = CHOICES)

class DemoForm(forms.ModelForm):
    class Meta:
        model = Demo

Я просмотрел исходный код Django. Все могут принимать массив выбора. Очевидно, что для некоторых из них это не имеет смысла, но это возможно.

Ответ 2

Вы можете обрабатывать это в форме (с модификацией моделей) следующим образом:

forms.NullBooleanField(
    widget=forms.RadioSelect(renderer=HorizontalRadioRendererSpace,
        choices=CHOICES),
    label='...',
    required=False)

Я думаю, что неплохо использовать NullBooleanField для данных, которые могут быть в трех состояниях: yes/no/unset.

Редактирование данных работает. Но большая проблема возникает, если вы хотите написать форму поиска для этих данных.

Тогда "пустые" значения могут иметь два значения:

  • Не заботьтесь об этом атрибуте. Включить все строки
  • Включить только эти строки, где столбец равен NULL.

Решение прост: используйте ChoiceField.

Подробнее здесь: https://github.com/guettli/programming-guidelines/blob/master/README.rst

Ответ 3

Вы можете изменить виджет поля в метафайле ModelForm:

CHOICES = (
            (None, "I do not know now"),
            (True, "Yes I acknowledge this"),
            (False, "No, I do not like this"),
           )
class DemoForm(forms.ModelForm):
    class Meta:
        model = Demo
        fields = ("demo_field",)
        widgets = {
              'demo_field': forms.RadioSelect(choices = CHOICES),
                  }

Ответ 4

Простым подходом было бы изменить выбор виджетов в вашей форме:

class YourForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(YourForm, self).__init__(*args, **kwargs)
        new_choices = ((1, 'I do not know now'),
                       (2, 'Yes I acknowledge this'),
                       (3, 'No, I do not like this'))
        self.fields['your_field'].widget.choices = new_choices