summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamiro Morales <cramm0@gmail.com>2012-01-15 01:36:14 +0000
committerRamiro Morales <cramm0@gmail.com>2012-01-15 01:36:14 +0000
commite308cfc0e155f51f14c8eb4e678c15c5f632ae30 (patch)
tree037ed46d6790adc32e1483c7240317e5ef31e38c
parent4e29b70b9dfb836a6ece537728f1ad9702786948 (diff)
Added support for specifying initial values to model formsets and inline 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
-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