1

I would want to display all NullBooleanFields in my application as radio buttons. What's the best way to do it?

Following template or something similar would be ideal. Just to allow rich styling and tone-of-voice different from plain "Yes/No/Unknown".

'''<li class="field-%s">
    <label class="%s" title="%s">%s</label>
    <label class="y"><input type="radio" name="%s" value="1" %s /> %s</label>
    <label class="n"><input type="radio" name="%s" value="0" %s /> %s</label>
    <label class="e"><input type="radio" name="%s" value=""  %s /> %s</label>
    </li>
''' % (
        field,
        field, help text, verbose_name,
        field, y, y_label,
        field, n, n_label,
        field, e, e_label
    )
fmalina
  • 6,120
  • 4
  • 37
  • 47
  • It's just that the default dropdown is not a good user experience. I agree that NullBooleanField should display as radio by default just like Adrian wanted to implement it originally http://groups.google.com/group/django-developers/msg/7456632f68f6b40a. He never got back to it, but I suppose we could fix it. – fmalina Aug 24 '10 at 12:32

2 Answers2

2

In the end I figured that setting widgets to RadioSelect one by one was less code even though I have a lot of NullBooleanFields. The <ul> producted by RadioSelect widget is enough structure to style on, even though it requires CSS3 selectors.

Not DRY, but less hassle. One needs to be pragmatic and move on.

If someone could provide code to change the default widget for NullBooleanField from NullBooleanSelect to RadioSelect on the forms.py level, I'd happily accept the answer.

fmalina
  • 6,120
  • 4
  • 37
  • 47
  • It is a kinda brutal way, but you could create your own ModelField, which only overwrites the formfield method. This formfield is again custom with your own widget. This way you don't have to adjust any forms. – Blackeagle52 Feb 14 '17 at 13:28
1

I just implemented a custom widget to do this:

class YesNoNARadioSelect(widgets.Widget):
    CHOICES=((True,'Yes'),(False,'No'),(None,'N/A'))

    def render(self,name,value,attrs=None):
        s=[]
        for c in self.CHOICES:
            extraAttrs=attrs.copy()
            extraAttrs.update(dict(type='radio',name=name,value=c[0]))
            if value==c[0]: extraAttrs['checked']='checked'
            extraAttrs=self.build_attrs(extraAttrs)
            s.append(format_html('<label><input {}/>{}</label>',flatatt(extraAttrs),c[1]))
        return S(''.join(s))

Seems to work for me, although I'd like to hear of anything that I'm doing wrong with it.

Adam Kerz
  • 919
  • 1
  • 6
  • 14