tags:

views:

1641

answers:

3

Hi,

I having trouble with a simple question : How to have some "disabled" field in a dropdown menu generated via a modelForm and choiceFied in the django Framework ?

At the moment, I cannot figure out how to obtain such an output : -- Root 1 entry -- (disabled) -- Elt 1 -- (not disabled) -- Root 2 entry -- (disabled)

Do you have any advice ?

Pierre

+3  A: 

Are you trying to create a menu in which the list items are separated into categories, and you don't want the categories themselves to be selectable?

If so, you can achieve this by having your template render the field using tags, e.g.

<select name="my_field" id="id_my_field">
<optgroup label="-- Root 1 entry --">
    <option value="1">Elt 1</option>
    <option value="2">Elt 2</option>
    <option value="3">Elt 3</option>
</optgroup>
<optgroup label="--- Root 2 entry ---">
    <option value="4">Elt 4</option>
    <option value="5">Elt 5</option>
</optgroup>
</select>
bryan
+4  A: 

Django's form widgets offer a way to pass a list of attributes that should be rendered on the <option> tag:

my_choices = ( ('one', 'One'), ('two', 'Two'))
class MyForm(forms.Form):
    some_field = forms.ChoiceField(choices=my_choices, 
                                   widget=forms.Select(attrs={'disabled':'disabled'}))

Unfortunately, this won't work for you because the attribute will be applied to EVERY option tag that is rendered. Django has no way to automatically know which should be enabled and which should be disabled.

In your case, I recommend writing a custom widget. It's pretty easy to do, and you don't have that much custom logic to apply. The docs on this are here. In short though:

  • subclass forms.Select, which is the default select renderer
  • in your subclass, implement the render(self, name, value, attrs) method. Use your custom logic to determine if the value qualifies as needing to be disabled. Have a look at the very short implementation of render in django/forms/widgets.py if you need inspriation.

Then, define your form field to use your custom widget:

class MyForm(forms.Form):
    some_field = forms.ChoiceField(choices=my_choices, 
                                   widget=MyWidget)
Jarret Hardie
This is a very nice solution, but the proper method to change the options' attributes is `render_option()` not `render()` (which renders the whole widget)
Jannis
+1  A: 

It seems django 1.1 will allow "optgroup". In django dev documentation : Django dev doc

This imho is a must have.

Regards,

Pierre