views:

1786

answers:

3

I'm trying to prepopulate the data in my django form based on some information, but NOT using ModelForm, so I can't just set the instance.

This seems like it should be really easy, but for some reason I can't find any documentation telling me how to do this. This is my form:

class MyForm(forms.Form):
  charfield1 = forms.CharField(max_length=3)
  charfield2 = forms.CharField(max_length=3)
  choicefield = forms.ModelChoiceField(MyModel.objects.all())

I tried just doing:

form = MyForm()
form.charfield1 = "foo"
form.charfield2 = "bar"
# a model choice field
form.choicefield = MyModel.objects.get(id=3)

which does not work.

+13  A: 

Try:

form = MyForm({'charfield1': 'foo', 'charfield2': 'bar'})

The constructor of Form objects can take a dictionary of field values. This creates a bound form, which can be used to validate the data and render the form as HTML with the data displayed. See the forms API documentation for more details.

Edit:

For the sake of completeness, if you do not want to bind the form, and you just want to declare initial values for some fields, you can use the following instead:

form = MyForm(initial={'charfield1': 'foo', 'charfield2': 'bar'})

See the documentation of initial values for details.

Ayman Hourieh
thanks - this works. However, it doesn't work with the foreign key to a model. I tried passing in the model instance itself in the dictionary, which throws an exception, and i tried passing in the pk/id, which doesn't fail, but doesn't pre-load it correctly in my form UI.
Cory
Using the object id should work. I've just tested it with a ModelChoiceField. Could you please show us your form definition?
Ayman Hourieh
added the form definition in the edit.
Cory
I tested again. The following works (2 is an id of an object in the model): MyForm({'charfield1': 'foo', 'charfield2': 'bar', 'choicefield': '2'}). Are you sure you are using an id that exists in the database? I can't think of anything else that may cause this at the moment.
Ayman Hourieh
strange, i added another field and it just started working....
Cory
+6  A: 

There are two ways of populating a Django form.

The first is to pass a dictionary as the first argument when you instantiate it (or pass it as the data kwarg, which is the same thing). This is what you do when you want to use POST data to populate and validate the form.

data_dict = {'charfield1': 'data1', 'charfield2': 'data2', 'choicefield': 3}
form = MyForm(data_dict)

However, this will trigger validation on the form, so only works if you are actually passing in valid and complete data to begin with - otherwise you will start off with errors.

The other way to populate a form is to use the initial parameter (documented here). This gives initial values for the form fields, but does not trigger validation. It's therefore suitable if you're not filling in all values, for example.

form = MyForm(initial=data_dict)

To populate a choicefield via initial, use the pk value.

Daniel Roseman
A: 

How would you write the HTML form though? If I'm editing an object and I specify initial values, the HTML would be (for example):

<input type="text" name="title" id="title" value="{{ form.initial.title }}" class="in" />

But then when I want to re-display the form if an invalid value is entered I need to use this:

<input type="text" name="title" id="title" value="{{ form.data.title }}" class="in" />

So my template now needs two different lines plus logic just to display the input field. Am I missing something obvious here??

Mike Stoddart
I have the feeling this is more a question than an answer...
Felix Kling