Django: Display NullBooleanField as Radio and defa

2020-06-23 03:44发布

I am successfully implementing NullBooleanField as radio buttons in several ways but the problem is that I can not set the default value to None.

Here is the code:

models.py:
class ClinicalData(models.Model):
      approved = models.NullBooleanField()
      ...

forms.py:
NA_YES_NO = ((None, 'N/A'), (True, 'Yes'), (False, 'No'))
class ClinicalDataForm(ModelForm):
      approved = forms.BooleanField(widget=forms.RadioSelect(choices=NA_YES_NO))
      class Meta:
           model = ClinicalData 

I tried the following methods: Set default:None in the model and/or setting inital:None in the form and also in the view in the form instance.
None of that was successfull. Im currently using CharField instead of NullBooleanField.
But is there some way to get this results with NullBooleanField???

5条回答
Deceive 欺骗
2楼-- · 2020-06-23 04:14

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.

查看更多
做自己的国王
3楼-- · 2020-06-23 04:15

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'
)
查看更多
戒情不戒烟
4楼-- · 2020-06-23 04:16

I've achieved this with Django 2.2.

You should be able to have the None radio option checked with a ChoiceField and RadioSelect widget. The trick is to set the None choice value to empty string ''.

The model field I used was a BooleanField with null=True which is essentially the same as the model field NullBooleanField.

approved = forms.ChoiceField(
    choices=[(True, 'Yes'), (False, 'No'), ('', 'N/A')],
    widget=forms.RadioSelect,
    required=False,
)
查看更多
三岁会撩人
5楼-- · 2020-06-23 04:17

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.

查看更多
家丑人穷心不美
6楼-- · 2020-06-23 04:21

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
查看更多
登录 后发表回答