I'm creating a Django form with a set of Radio buttons (as a single RadioSelect field), and I'd like to have some of the buttons grayed out. However, given that the RadioSelect field is a single field on the form, I haven't found a way to do that.
class OrderStatusForm(forms.Form):
os = Order_Status.objects.values_list('id', 'status')
status = forms.ChoiceField(choices=os, widget=forms.RadioSelect())
def makeForm():
newForm = OrderStatusForm()
# next line disables all radio buttons.
newForm.fields['status'].widget.attrs['disabled'] = True
Is there some way to selectively disable the individual radio buttons? Or do I just have to not put the disabled options in the list in the first place?
Further research turned up the fact that the RadioSelect renderer
can be replaced, and passed in as a parameter to the initial widget creation function. So I created my own renderer, and attached a list of Booleans, indicating which Radio buttons should be disabled.
The renderer adds a disabled attribute to each Radio button widget as needed, then the force_unicode turns the widget's attributes into HTML that include a disabled="True"
value.
from django.utils.safestring import mark_safe
from django.utils.encoding import force_unicode
class RandomRenderer(forms.RadioSelect.renderer):
""" Modifies some of the Radio buttons to be disabled in HTML,
based on an externally-appended Actives list. """
def render(self):
if not hasattr(self, "actives"): # oops, forgot to add an Actives list
return self.original_render()
return self.my_render()
def original_render(self):
return mark_safe(u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>'
% force_unicode(w) for w in self]))
def my_render(self):
midList = []
for x, wid in enumerate(self):
if self.actives[x] == False:
wid.attrs['disabled'] = True
midList.append(u'<li>%s</li>' % force_unicode(wid))
finalList = mark_safe(u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>'
% w for w in midList]))
return finalList
class OrderStatusForm(forms.Form):
os = Order_Status.objects.values_list('id', 'status', 'reason')
activeList = [True, False, True, False, True, False,]
newStatus = forms.ChoiceField(widget=forms.RadioSelect(
renderer=RandomRenderer), choices=os)
newStatus.widget.renderer.actives = activeList
It's a little kludgy - I'm just sticking the actives list directly onto the renderer, which works (love Python's duck-typing), but would be cleaner if I passed the list in some constructors. Unfortunately I had problems with that, so took the easy way out. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With