Hello Visitor! Login or Sign Up

Custom Rendering for Radio Buttons In Django NewForms

Django is a great framework and I like the NewForms library a lot, especially the as_table() and as_ul() type form rendering shortcuts but sometimes you don't want the default rendering with labels and everything.

In particular, I was trying to get a questionnaire effect like the one below :

Radio Button Questionnaire

I'd really like to be able to do that with code like :

<table>
        ...
        {% for field in form %}
        <tr>
         <td>{{ field.label }}</td>
         {{ field }}
        </tr>
        {% if field.errors %}
        <tr>
         <td colspan="6">{{ field.errors }}</td>
        </tr>
        {% endif %}
        {% endfor %}
        ...
         </table>
        

CSS removed for a bit more clarity.

What I really wanted was each radio button in the list of choices to go in its own table cell so that my {{field}} would wrap all it's own input boxes. I also wanted to set a css style to each of those input boxes.

Now I don't know if this is the best way but this is what I came up with. I'm writing this on a < 1.0 version of Django here so things can change.

from django.newforms.widgets import RadioFieldRenderer, RadioInput
        from django.utils.encoding import StrAndUnicode, force_unicode

        class MyRadioInput(RadioInput):
            '''
            An object used by RadioFieldRenderer that represents a single
            <input type='radio'>.
            '''

            def __unicode__(self):
                return mark_safe(u'%s' % (self.tag(),))

        class MyRadioRenderer(RadioFieldRenderer):
            def render(self):
                '''Outputs a <td> for this set of radio fields.'''
                return mark_safe(u'
'.join([u'<td class="qcol">%s</td>'
                        % force_unicode(w) for w in self]))

            def __iter__(self):
                for i, choice in enumerate(self.choices):
                    yield MyRadioInput(self.name, self.value, self.attrs.copy(), choice, i)
        

and then to use it (in my view) :

CHOICES = ((4,'Strongly Agree'),
                              (3,'Agree'),
                              (2,'Neutral'),
                              (1,'Disagree'),
                              (0,'Strongly Disagree'),)

        class LoveDjangoForm(forms.Form):
            a_question  = forms.ChoiceField(initial=2,label="Gotta love Django",choices=CHOICES,widget=forms.RadioSelect(renderer=MyRadioRenderer))
        

The key part is of course the widget=forms.RadioSelect(renderer=MyRadioRenderer)

You can see the result (and test your love style!) at this love style test page.

Not the most complex thing to puzzle out and it only took a few minutes. Overall, it's nice to have a framework that gives you useful shortcuts 90% of the time but doesn't handcuff you for the remaining 10%.

Comments

© 2006 - 2013 Automatic Romantic | Terms of Use | Privacy Policy | Developer Blog

Web Design Inspired by Andreas Viklund Some icons by Mark James