Есть ли виджет в Django 1.0.2 для рендеринга models.BooleanField
в качестве двух переключателей вместо флажка?
Django BooleanField как переключатели?
Ответ 1
Вы можете сделать это, переопределив определение поля в 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
Ответ 2
Django 1.2 добавила опцию "виджетов" для моделей:
В ваших 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 db, который также сохраняет логические значения как значения 1/0, и, похоже, он работает нормально, не используя специальную функцию принуждения.
Ответ 3
Изменив Даниэля Роземана немного, вы можете исправить ошибку bool ( "False" ) = True, просто используя вместо этого ints:
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
Ответ 4
В 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.')
])}
Ответ 5
Здесь функция быстрого и грязного использования, использующая лямбда, которая обходит проблему "False" → True:
...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...
Ответ 6
Здесь самый простой подход, который я мог найти (я использую Django 1.5):
class MyModelForm(forms.ModelForm):
yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'),
(False, 'No')]))
Ответ 7
Также помните, что 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
Ответ 8
Как есть проблема в @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
Теперь это будет работать:)
Ответ 9
То же, что и ответ @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 +
Ответ 10
Другое решение:
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)