Neo
Neo

Reputation: 5228

django : set default value for formset_factory form element

Model:

class AssociatedFileCourse(models.Model)
  file_original = models.FileField(upload_to = 'assets/associated_files')
  session = models.ForeignKey(Session)
  title = models.CharField(max_length=500)

Form:

class AddAssociatedFilesForm(ModelForm):
  class Meta:
    model = AssociatedFileCourse

If I had to create a single form from above defination and set some initial value, It could have done using initial parameter like

form = AddAssociatedFilesForm(initial={'session': Session.objects.get(pk=id)})

how to set the initial form values when creating a formset_factory forms like:

AddAssociatedFilesFormSet = formset_factory(AddAssociatedFilesForm)
form = AddAssociatedFilesFormSet()

Upvotes: 2

Views: 7231

Answers (2)

JCotton
JCotton

Reputation: 11760

You want to use modelformset_factory, which is tailored to create and act on formsets of Model instances.

from django.forms.models import modelformset_factory

# create the formset by specifying the Model and Form to use
AddAssociatedFilesFormSet = modelformset_factory(AssociatedFileCourse, form=AddAssociatedFilesForm)

# Because you aren't doing anything special with your custom form,
# you don't even need to define your own Form class
AddAssociatedFilesFormSet = modelformset_factory(AssociatedFileCourse)

By default a Model formset will display a form for every Model instance - i.e. Model.objects.all(). In addition you'll have blank forms allowing you to create new Model instances. The number of blank forms is subject to the max_num and extra kwargs passed to modelformset_factory().

If you want initial data you can specify it with the initial kwarg when generating the formset. Note, the initial data needs to be inside a list.

formset = AddAssociatedFilesFormSet(queryset=AssociatedFileCourse.objects.none(),
                                    initial=[{'session': Session.objects.get(pk=id)}])

That should look like you want it. However, you cannot (in current Django versions at least) create a Model formset with existing Model instances and initial data for the extra forms. That's why the objects.none() queryset is there. Set it to objects.all() or remove the queryset kwarg and - if you have instances - the extra forms will not have the initial data.

Further reading on Model formsets with initial data - see this post.

Upvotes: 3

Umang
Umang

Reputation: 5266

You would do it in the same way, except using a list of values in the dictionary rather than just a value.

From Django docs on formsets:

>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
>>> formset = ArticleFormSet(initial=[
...     {'title': u'Django is now open source',
...      'pub_date': datetime.date.today()},
... ])

>>> for form in formset:
...     print form.as_table()
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr>
<tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr>
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr>
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr>
<tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
<tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>

Upvotes: 2

Related Questions