Django BooleanField как переключатели? - PullRequest
54 голосов
/ 13 мая 2009

Есть ли в Django 1.0.2 виджет для отображения models.BooleanField в виде двух переключателей вместо флажка?

Ответы [ 10 ]

85 голосов
/ 18 октября 2010

В Django 1.2 добавлена ​​мета-опция "widgets" для моделей:

В вашем файле models.py укажите «варианты» для вашего логического поля:

BOOL_CHOICES = ((True, 'Yes'), (False, 'No'))

class MyModel(models.Model):
    yes_or_no = models.BooleanField(choices=BOOL_CHOICES)

Затем в вашем файле forms.py укажите виджет RadioSelect для этого поля:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        widgets = {
            'yes_or_no': forms.RadioSelect
        }

Я протестировал это с базой данных SQLite, которая также хранит логические значения как значения 1/0, и, кажется, работает нормально без пользовательской функции принуждения.

61 голосов
/ 13 мая 2009

Вы можете сделать это, переопределив определение поля в ModelForm:

class MyModelForm(forms.ModelForm):
    boolfield = forms.TypedChoiceField(
                   coerce=lambda x: x == 'True',
                   choices=((False, 'False'), (True, 'True')),
                   widget=forms.RadioSelect
                )

    class Meta:
         model = MyModel
30 голосов
/ 10 сентября 2009

Немного изменив ответ Даниэля Роземана, вы можете исправить ошибку bool ("False") = Истинно, просто используя вместо этого целые числа:

class MyModelForm(forms.ModelForm):
    boolfield = forms.TypedChoiceField(coerce=lambda x: bool(int(x)),
                   choices=((0, 'False'), (1, 'True')),
                   widget=forms.RadioSelect
                )

class Meta:
     model = MyModel
10 голосов
/ 19 августа 2014

В Django 1.6 у меня сработало следующее:

class EmailSettingsForm(ModelForm):

    class Meta:
        model = EmailSetting
        fields = ['setting']
        widgets = {'setting': RadioSelect(choices=[
            (True, 'Keep updated with emails.'),
            (False, 'No, don\'t email me.')             
        ])}
10 голосов
/ 02 июля 2014

Вот самый простой подход, который я смог найти (я использую Django 1.5):

class MyModelForm(forms.ModelForm):
    yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'), 
                                                            (False, 'No')]))
5 голосов
/ 12 января 2012

То же, что и ответ @ eternicode, но без изменения модели:

class MyModelForm(forms.ModelForm):
    yes_no = forms.RadioSelect(choices=[(True, 'Yes'), (False, 'No')])

    class Meta:
        model = MyModel
        widgets = {'boolfield': yes_no}

Я думаю, что это работает только в Django 1.2 +

5 голосов
/ 27 мая 2010

Вот быстрая и грязная принудительная функция с использованием лямбды, которая решает проблему «Ложь» -> Истинная проблема:

...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...
3 голосов
/ 05 марта 2013

Другое решение:

from django import forms
from django.utils.translation import ugettext_lazy as _

def RadioBoolean(*args, **kwargs):
    kwargs.update({
        'widget': forms.RadioSelect,
        'choices': [
            ('1', _('yes')),
            ('0', _('no')),
        ],
        'coerce': lambda x: bool(int(x)) if x.isdigit() else False,
    })
    return forms.TypedChoiceField(*args, **kwargs)
3 голосов
/ 20 июля 2011

Поскольку в ответе @Daniel Roseman есть проблема, bool ('False') -> True, поэтому теперь я объединил два ответа, чтобы найти одно решение.

def boolean_coerce(value):
    # value is received as a unicode string
   if str(value).lower() in ( '1', 'true' ):
       return True
   elif str(value).lower() in ( '0', 'false' ):
       return False
   return None

class MyModelForm(forms.ModelForm):
boolfield = forms.TypedChoiceField(coerce= boolean_coerce,
               choices=((False, 'False'), (True, 'True')),
               widget=forms.RadioSelect
            )

class Meta:
     model = MyModel

Теперь это будет работать:)

3 голосов
/ 18 июня 2009

Также помните, что MySQL использует tinyint для Boolean, поэтому True / False на самом деле 1/0. Я использовал эту принудительную функцию:

def boolean_coerce(value):
    # value is received as a unicode string
    if str(value).lower() in ( '1', 'true' ):
        return True
    elif str(value).lower() in ( '0', 'false' ):
        return False
    return None
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...