web-dev-qa-db-ja.com

DjangoラジオボタンとしてのBooleanField?

Django 1.0.2にmodels.BooleanFieldをチェックボックスではなく2つのラジオボタンとしてレンダリングするウィジェットがありますか?

54
dar

これを行うには、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
61
Daniel Roseman

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でこれをテストしましたが、カスタム強制関数がなくても正常に機能するようです。

85
eternicode

ダニエルローズマンの答えを少し修正すると、代わりに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
30

私が見つけることができる最も簡単なアプローチは次のとおりです(Django 1.5)を使用しています):

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

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
Kevin White

@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
yprez

以下は、ラムダを使用した「False」-> True問題を回避する簡単で汚い強制関数です。

...
boolfield = forms.TypedChoiceField(coerce=lambda x: x and (x.lower() != 'false'),
...
5
af__

また、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
3

他の解決策:

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
matinfo

@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

今、これは動作します:)

3
Ahsan