Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added support for specifying initial values to model formsets and inl…

…ine formsets.

This make them consistent with the similar capability of regular
formsets. Thanks to simon29 form the report and to Claude Paroz for the
patch.

Fixes #14574.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17373 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit e308cfc0e155f51f14c8eb4e678c15c5f632ae30 1 parent 4e29b70
@ramiro ramiro authored
View
2  django/forms/formsets.py
@@ -122,7 +122,7 @@ def _construct_form(self, i, **kwargs):
if self.is_bound:
defaults['data'] = self.data
defaults['files'] = self.files
- if self.initial:
+ if self.initial and not 'initial' in kwargs:
try:
defaults['initial'] = self.initial[i]
except IndexError:
View
11 django/forms/models.py
@@ -418,6 +418,7 @@ class BaseModelFormSet(BaseFormSet):
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
queryset=None, **kwargs):
self.queryset = queryset
+ self.initial_extra = kwargs.pop('initial', None)
defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
defaults.update(kwargs)
super(BaseModelFormSet, self).__init__(**defaults)
@@ -448,6 +449,12 @@ def _construct_form(self, i, **kwargs):
kwargs['instance'] = self._existing_object(pk)
if i < self.initial_form_count() and not kwargs.get('instance'):
kwargs['instance'] = self.get_queryset()[i]
+ if i >= self.initial_form_count() and self.initial_extra:
+ # Set initial values for extra forms
+ try:
+ kwargs['initial'] = self.initial_extra[i-self.initial_form_count()]
+ except IndexError:
+ pass
return super(BaseModelFormSet, self)._construct_form(i, **kwargs)
def get_queryset(self):
@@ -674,7 +681,7 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
class BaseInlineFormSet(BaseModelFormSet):
"""A formset for child objects related to a parent."""
def __init__(self, data=None, files=None, instance=None,
- save_as_new=False, prefix=None, queryset=None):
+ save_as_new=False, prefix=None, queryset=None, **kwargs):
from django.db.models.fields.related import RelatedObject
if instance is None:
self.instance = self.fk.rel.to()
@@ -687,7 +694,7 @@ def __init__(self, data=None, files=None, instance=None,
queryset = self.model._default_manager
qs = queryset.filter(**{self.fk.name: self.instance})
super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
- queryset=qs)
+ queryset=qs, **kwargs)
def initial_form_count(self):
if self.save_as_new:
View
6 docs/releases/1.4.txt
@@ -556,6 +556,12 @@ Django 1.4 also includes several smaller improvements worth noting:
* The MySQL database backend can now make use of the savepoint feature
implemented by MySQL version 5.0.3 or newer with the InnoDB storage engine.
+* It is now possible to pass initial values to the model forms that are part of
+ both model formsets and inline model formset as returned from factory
+ functions ``modelformset_factory`` and ``inlineformset_factory`` respectively
+ just like with regular formsets. However, initial values only apply to extra
+ forms i.e. those which are not bound to an existing model instance.
+
Backwards incompatible changes in 1.4
=====================================
View
2  docs/topics/forms/formsets.txt
@@ -53,6 +53,8 @@ Formsets can also be indexed into, which returns the corresponding form. If you
override ``__iter__``, you will need to also override ``__getitem__`` to have
matching behavior.
+.. _formsets-initial-data:
+
Using initial data with a formset
---------------------------------
View
11 docs/topics/forms/modelforms.txt
@@ -617,6 +617,17 @@ exclude::
>>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))
+Providing initial values
+------------------------
+
+.. versionadded:: 1.4
+
+As with regular formsets, it is possible to :ref:`specify initial data
+<formsets-initial-data>` for forms in the formset by specifying an ``initial``
+parameter when instantiating the model formset class returned by
+``modelformset_factory``. However, with model formsets the initial values only
+apply to extra forms, those which are not bound to an existing object instance.
+
.. _saving-objects-in-the-formset:
Saving objects in the formset
View
19 tests/regressiontests/model_formsets_regress/tests.py
@@ -204,6 +204,17 @@ def test_save_as_new_with_new_inlines(self):
["<Host: matrix.de.eu.dal.net>", "<Host: tranquility.hub.dal.net>"]
)
+ def test_initial_data(self):
+ user = User.objects.create(username="bibi", serial=1)
+ UserSite.objects.create(user=user, data=7)
+ FormSet = inlineformset_factory(User, UserSite, extra=2)
+
+ formset = FormSet(instance=user, initial=[{'data': 41}, {'data': 42}])
+ self.assertEqual(formset.forms[0].initial['data'], 7)
+ self.assertEqual(formset.extra_forms[0].initial['data'], 41)
+ self.assertTrue(u'value="42"' in formset.extra_forms[1].as_p())
+
+
class FormsetTests(TestCase):
def test_error_class(self):
'''
@@ -230,6 +241,14 @@ def test_error_class(self):
self.assertTrue(isinstance(form.errors, ErrorDict))
self.assertTrue(isinstance(form.non_field_errors(), ErrorList))
+ def test_initial_data(self):
+ User.objects.create(username="bibi", serial=1)
+ Formset = modelformset_factory(User, extra=2)
+ formset = Formset(initial=[{'username': u'apollo11'}, {'username': u'apollo12'}])
+ self.assertEqual(formset.forms[0].initial['username'], "bibi")
+ self.assertEqual(formset.extra_forms[0].initial['username'], "apollo11")
+ self.assertTrue(u'value="apollo12"' in formset.extra_forms[1].as_p())
+
class CustomWidget(forms.CharField):
pass
Please sign in to comment.
Something went wrong with that request. Please try again.