tags:

views:

683

answers:

4

Hi All,

I have a model formset that I need to pass the keyword initial in to (to have some initial values in the formset, such as date set to today). As far as I can tell, the queryset argument (which defaults to YourModel.objects.all()) overrides this ability for initial empty forms to be created. I specified the queryset as: YourModel.objects.none(), which prevents it from filling in the formset with entries from the database, but I still can't figure out how to pass initial in effectively. Do I need to subclass a method from ModelForm?

A: 

A simple solution could be that you pass a form that extends a modelform() to a formset (rather than modelformset).

That way you can set initial values in the form.

Lakshman Prasad
Can you elaborate on this? I'm not sure I understand what you mean.
Vince
A: 

I think you can use initial argument, as with regular formsets http://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-initial-data-with-a-formset

Dmitry Shevchenko
Yes, if it was a regular formset this is possible. However this formset was generated using modelformset_factory().
Vince
A: 

It is still possible to pass initial to a ModelFormSet.

from django.forms.models import modelformset_factory
from example.models import ExampleModel

ExampleModelFormSet = modelformset_factory(ExampleModel)
formset = ExampleModelFormSet(initial=[{'name': 'Some Name'},
                                       {'name': 'Another Name'}])

If this is not what your after, can you explain your question more.

EDIT:

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2)
formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(),
                              initial=[{'name': 'Some Name'},
                                       {'name': 'Another Name'}])
Gerry
By default Django's model formsets populate themselves with the results of yourmodel.objects.all(). This can be reversed with queryset=yourmodel.objects.none(), but this still doesn't allow initial values. Something about having the queryset and initial keywords set makes this not work.
Vince
How does it not work, what is it not doing? By using the updated code I get a formset from an empty queryset and initial values filled in.
Gerry
Yeah.. this is the way to go. I agree.
simplyharsh
+3  A: 

You passing an empty queryset to ModelFormset, i guess.

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2)
formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(),
                          initial=[{'name': 'Some Name'},
                                   {'name': 'Another Name'}])

This indeed is a way to do what you want to do. It makes sense when you pass an empty queryset. Else, initial values will override the model's database value.

And if I suppose, you are passing a non-empty queryset, and yet want your extra forms to be filled will initial values, overriding can be the option.

from django.forms.models import modelformset_factory  
ExampleFormset = modelformset_factory(OpenIDProfile, extra=3)

class myFormset(ExampleFormset):

    def _construct_form(self, i, **kwargs):
        """
        Instantiates and returns the i-th form instance in a formset.
        """
        if self.is_bound and i < self.initial_form_count():
            pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
            pk = self.data[pk_key]
            pk_field = self.model._meta.pk
            pk = pk_field.get_db_prep_lookup('exact', pk)
            if isinstance(pk, list):
                pk = pk[0]
            kwargs['instance'] = self._existing_object(pk)
        if i < self.initial_form_count() and not kwargs.get('instance'):
            kwargs['instance'] = self.get_queryset()[i]

        defaults = {'auto_id': self.auto_id, 'prefix': self.add_prefix(i)}
        if self.data or self.files:
            defaults['data'] = self.data
            defaults['files'] = self.files
        # Check to confirm we are not overwriting the database value.
        if not i in range(self.initial_form_count()) and self.initial:
            try:
                defaults['initial'] = self.initial[i - self.initial_form_count()]
            except IndexError:
                pass
        # Allow extra forms to be empty.
        if i >= self.initial_form_count():
            defaults['empty_permitted'] = True
        defaults.update(kwargs)
        form = self.form(**defaults)
        self.add_fields(form, i)        
        return form

initial is list of dicts. Its desirable to have items in list exactly equal to the number of extra.

simplyharsh