Django: Display NullBooleanField as Radio and default to None

試著忘記壹切 提交于 2019-12-04 12:38:21

For some odd reason - I didn't check it at the Django code -, as soon as you provide a custom widget for a NullBooleanField, it doesn't accept the values you expect (None, True or False) anymore.

By analyzing the built-in choices attribute, I found out that those values are equal to, respectively, 1, 2 and 3.

So, this is the quick-and-dirty solution I fould to stick to radio buttons with 'Unknown' as default:

class ClinicalDataForm(forms.ModelForm):
    class Meta:
        model = ClinicalData

    def __init__(self, *args, **kwargs):
        super(ClinicalDataForm, self).__init__(*args, **kwargs)
        approved = self.fields['approved']
        approved.widget = forms.RadioSelect(
            choices=approved.widget.choices)
        approved.initial = '1'

It doesn't look good and I wouldn't use it unless very necessary. But there it is, just in case.

I know this has been answered for a while now, but I was also trying to solve this problem and came across this question.

After trying emyller's solution, it seemed to work, however when I looked at the form's self.cleaned_data, I saw that the values I got back were all either True or None, no False values were recorded.

I looked into the Django code and saw that while the normal NullBooleanField select does indeed map None, True, False to 1, 2, 3 respectively, the RadioSelect maps 1 to True, 0 to False and any other value to None

This is what I ended up using:

my_radio_select = forms.NullBooleanField(
    required=False,
    widget=widgets.RadioSelect(choices=[(1, 'Yes'), (0, 'No'), (2, 'N/A')]),
    initial=2,  # Set initial to 'N/A'
)

For what it's worth, the other answers given here no longer apply in Django 1.7. Setting choices to [(True, "Yes"), (False, "No"), (None, "N/A")] works just fine.

For me in Django 1.7 None value is not selected by default (despite what Craig claims). I subclassed RadioSelect, it helped in my case:

from django.forms.widgets import RadioSelect
from django.utils.translation import ugettext_lazy

class NullBooleanRadioSelect(RadioSelect):
    def __init__(self, *args, **kwargs):
        choices = (
            (None, ugettext_lazy('Unknown')),
            (True, ugettext_lazy('Yes')),
            (False, ugettext_lazy('No'))
        )
        super(NullBooleanRadioSelect, self).__init__(choices=choices, *args, **kwargs)

    _empty_value = None
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!