summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/forms/formsets.py2
-rw-r--r--django/forms/models.py11
-rw-r--r--docs/releases/1.4.txt6
-rw-r--r--docs/topics/forms/formsets.txt2
-rw-r--r--docs/topics/forms/modelforms.txt11
-rw-r--r--tests/regressiontests/model_formsets_regress/tests.py19
6 files changed, 48 insertions, 3 deletions
diff --git a/django/forms/formsets.py b/django/forms/formsets.py
index 9cdd05198c..dcd2f017e7 100644
--- a/django/forms/formsets.py
+++ b/django/forms/formsets.py
@@ -122,7 +122,7 @@ class BaseFormSet(StrAndUnicode):
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:
diff --git a/django/forms/models.py b/django/forms/models.py
index b65f067846..15d50419d4 100644
--- a/django/forms/models.py
+++ b/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 @@ class BaseModelFormSet(BaseFormSet):
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 @@ class BaseInlineFormSet(BaseModelFormSet):
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:
diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt
index ea3e9a7fc9..9b3c219d31 100644
--- a/docs/releases/1.4.txt
+++ b/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
=====================================
diff --git a/docs/topics/forms/formsets.txt b/docs/topics/forms/formsets.txt
index 37c3067f55..b524c24ad2 100644
--- a/docs/topics/forms/formsets.txt
+++ b/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
---------------------------------
diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt
index 832a3acff0..cd1f43ae49 100644
--- a/docs/topics/forms/modelforms.txt
+++ b/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
diff --git a/tests/regressiontests/model_formsets_regress/tests.py b/tests/regressiontests/model_formsets_regress/tests.py
index 35a794aa78..613d77616c 100644
--- a/tests/regressiontests/model_formsets_regress/tests.py
+++ b/tests/regressiontests/model_formsets_regress/tests.py
@@ -204,6 +204,17 @@ class InlineFormsetTests(TestCase):
["<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 @@ class FormsetTests(TestCase):
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