Django 1.0.2にmodels.BooleanField
をチェックボックスではなく2つのラジオボタンとしてレンダリングするウィジェットがありますか?
これを行うには、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
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
}
これは、ブール値を1/0値として保存するSQLite dbでこれをテストしましたが、カスタム強制関数がなくても正常に機能するようです。
ダニエルローズマンの答えを少し修正すると、代わりにintを使用するだけでbool( "False")= Trueの問題を簡潔に修正できます。
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
私が見つけることができる最も簡単なアプローチは次のとおりです(Django 1.5)を使用しています):
class MyModelForm(forms.ModelForm):
yes_no = forms.BooleanField(widget=RadioSelect(choices=[(True, 'Yes'),
(False, 'No')]))
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.')
])}
@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+
以下は、ラムダを使用した「False」-> True問題を回避する簡単で汚い強制関数です。
...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...
また、MySQLはブール値にtinyintを使用するため、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
他の解決策:
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)
@Daniel Rosemanの答え、bool( 'False')-> Trueに問題があるので、ここで2つの答えを組み合わせて1つのソリューションを作成しました。
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
今、これは動作します:)