Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the selected value on a Django forms.ChoiceField

Here is the field declaration in a form:

max_number = forms.ChoiceField(widget = forms.Select(), 
    choices = ([('1','1'), ('2','2'),('3','3'), ]), initial='3', required = True,)

I would like to set the initial value to be 3 and this doesn't seem to work. I have played about with the param, quotes/no quotes, etc... but no change.

Could anyone give me a definitive answer if it is possible? And/or the necessary tweak in my code snippet?

I am using Django 1.0

like image 286
thebiglife Avatar asked Mar 18 '09 09:03

thebiglife


People also ask

What is form Is_valid () in Django?

The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.

What is a widget in Django?

A widget is Django's representation of an HTML input element. The widget handles the rendering of the HTML, and the extraction of data from a GET/POST dictionary that corresponds to the widget. The HTML generated by the built-in widgets uses HTML5 syntax, targeting <!


5 Answers

Try setting the initial value when you instantiate the form:

form = MyForm(initial={'max_number': '3'}) 
like image 71
Tom Avatar answered Oct 14 '22 13:10

Tom


This doesn't touch on the immediate question at hand, but this Q/A comes up for searches related to trying to assign the selected value to a ChoiceField.

If you have already called super().__init__ in your Form class, you should update the form.initial dictionary, not the field.initial property. If you study form.initial (e.g. print self.initial after the call to super().__init__), it will contain values for all the fields. Having a value of None in that dict will override the field.initial value.

e.g.

class MyForm(forms.Form):
    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        # assign a (computed, I assume) default value to the choice field
        self.initial['choices_field_name'] = 'default value'
        # you should NOT do this:
        self.fields['choices_field_name'].initial = 'default value'
like image 40
colinta Avatar answered Oct 14 '22 11:10

colinta


You can also do the following. in your form class def:

max_number = forms.ChoiceField(widget = forms.Select(), 
                 choices = ([('1','1'), ('2','2'),('3','3'), ]), initial='3', required = True,)

then when calling the form in your view you can dynamically set both initial choices and choice list.

yourFormInstance = YourFormClass()

yourFormInstance.fields['max_number'].choices = [(1,1),(2,2),(3,3)]
yourFormInstance.fields['max_number'].initial = [1]

Note: the initial values has to be a list and the choices has to be 2-tuples, in my example above i have a list of 2-tuples. Hope this helps.

like image 23
Burton Williams Avatar answered Oct 14 '22 12:10

Burton Williams


I ran into this problem as well, and figured out that the problem is in the browser. When you refresh the browser is re-populating the form with the same values as before, ignoring the checked field. If you view source, you'll see the checked value is correct. Or put your cursor in your browser's URL field and hit enter. That will re-load the form from scratch.

like image 36
Dave Avatar answered Oct 14 '22 12:10

Dave


Both Tom and Burton's answers work for me eventually, but I had a little trouble figuring out how to apply them to a ModelChoiceField.

The only trick to it is that the choices are stored as tuples of (<model's ID>, <model's unicode repr>), so if you want to set the initial model selection, you pass the model's ID as the initial value, not the object itself or it's name or anything else. Then it's as simple as:

form = EmployeeForm(initial={'manager': manager_employee_id})

Alternatively the initial argument can be ignored in place of an extra line with:

form.fields['manager'].initial = manager_employee_id
like image 30
orlade Avatar answered Oct 14 '22 11:10

orlade