Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django forms: default values for bound forms

Tags:

forms

django

With this form:

class Form(forms.Form):
    name = forms.CharField(required=False, initial='Hello world')

If I do something like this in the view:

form = Form(request.GET)
if form.is_valid():
    name = form.cleaned_data['name']

Then initial value of name is lost even if request.GET does not contain name as key. Is there any workaround? I would like initial values work to bound forms as "default values".

like image 749
clime Avatar asked Apr 15 '13 23:04

clime


2 Answers

request.GET is a dictionary like object.

initial only works in case of unbound form.

Forms have an attribute named data. This attribute is provided as first positional argument or as a data keyword argument during form initialization.

Bound forms are those in which you provide some data as first argument to the form and unbound form has data attribute set as None.

Here in your initialization of form form=Form(request.GET), you are providing the first positional argument, so data attribute is being set on the form and it becomes a bound form. This happens even if request.GET is an empty dictionary. And since your form becomes a bound form so initial of name field has no effect on it.

So, In you GET request you should either do:

form = Form()

and your initial of name field would be honoured.

Or, if you want to read name from request.GET and if its there then want to use it instead of field's initial then have following in your view.

name = request.GET.get(name)
form_level_initial = {}
if name:
    form_level_initial['name'] = name
form = Form(initial=form_level_initial)
like image 159
Akshar Raaj Avatar answered Oct 03 '22 01:10

Akshar Raaj


By slightly modifying Gonzalo's solution, this is the right way:

class Form(forms.Form):
    name = forms.CharField(required=False, initial='Hello world')

    def clean_name(self):
        if not self['name'].html_name in self.data:
            return self.fields['name'].initial
        return self.cleaned_data['name']

If you need this, you may have a look at django-filter app. I have discovered it quite recently.

like image 34
clime Avatar answered Oct 03 '22 02:10

clime