mirror of https://github.com/django/django.git
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
This commit is contained in:
parent
4e29b70b9d
commit
e308cfc0e1
|
@ -122,7 +122,7 @@ class BaseFormSet(StrAndUnicode):
|
||||||
if self.is_bound:
|
if self.is_bound:
|
||||||
defaults['data'] = self.data
|
defaults['data'] = self.data
|
||||||
defaults['files'] = self.files
|
defaults['files'] = self.files
|
||||||
if self.initial:
|
if self.initial and not 'initial' in kwargs:
|
||||||
try:
|
try:
|
||||||
defaults['initial'] = self.initial[i]
|
defaults['initial'] = self.initial[i]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
|
|
@ -418,6 +418,7 @@ class BaseModelFormSet(BaseFormSet):
|
||||||
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
|
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
|
||||||
queryset=None, **kwargs):
|
queryset=None, **kwargs):
|
||||||
self.queryset = queryset
|
self.queryset = queryset
|
||||||
|
self.initial_extra = kwargs.pop('initial', None)
|
||||||
defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
|
defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
super(BaseModelFormSet, self).__init__(**defaults)
|
super(BaseModelFormSet, self).__init__(**defaults)
|
||||||
|
@ -448,6 +449,12 @@ class BaseModelFormSet(BaseFormSet):
|
||||||
kwargs['instance'] = self._existing_object(pk)
|
kwargs['instance'] = self._existing_object(pk)
|
||||||
if i < self.initial_form_count() and not kwargs.get('instance'):
|
if i < self.initial_form_count() and not kwargs.get('instance'):
|
||||||
kwargs['instance'] = self.get_queryset()[i]
|
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)
|
return super(BaseModelFormSet, self)._construct_form(i, **kwargs)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
@ -674,7 +681,7 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
|
||||||
class BaseInlineFormSet(BaseModelFormSet):
|
class BaseInlineFormSet(BaseModelFormSet):
|
||||||
"""A formset for child objects related to a parent."""
|
"""A formset for child objects related to a parent."""
|
||||||
def __init__(self, data=None, files=None, instance=None,
|
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
|
from django.db.models.fields.related import RelatedObject
|
||||||
if instance is None:
|
if instance is None:
|
||||||
self.instance = self.fk.rel.to()
|
self.instance = self.fk.rel.to()
|
||||||
|
@ -687,7 +694,7 @@ class BaseInlineFormSet(BaseModelFormSet):
|
||||||
queryset = self.model._default_manager
|
queryset = self.model._default_manager
|
||||||
qs = queryset.filter(**{self.fk.name: self.instance})
|
qs = queryset.filter(**{self.fk.name: self.instance})
|
||||||
super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
|
super(BaseInlineFormSet, self).__init__(data, files, prefix=prefix,
|
||||||
queryset=qs)
|
queryset=qs, **kwargs)
|
||||||
|
|
||||||
def initial_form_count(self):
|
def initial_form_count(self):
|
||||||
if self.save_as_new:
|
if self.save_as_new:
|
||||||
|
|
|
@ -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
|
* 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.
|
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
|
Backwards incompatible changes in 1.4
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
|
|
@ -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
|
override ``__iter__``, you will need to also override ``__getitem__`` to have
|
||||||
matching behavior.
|
matching behavior.
|
||||||
|
|
||||||
|
.. _formsets-initial-data:
|
||||||
|
|
||||||
Using initial data with a formset
|
Using initial data with a formset
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
|
|
@ -617,6 +617,17 @@ exclude::
|
||||||
|
|
||||||
>>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))
|
>>> 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:
|
||||||
|
|
||||||
Saving objects in the formset
|
Saving objects in the formset
|
||||||
|
|
|
@ -204,6 +204,17 @@ class InlineFormsetTests(TestCase):
|
||||||
["<Host: matrix.de.eu.dal.net>", "<Host: tranquility.hub.dal.net>"]
|
["<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):
|
class FormsetTests(TestCase):
|
||||||
def test_error_class(self):
|
def test_error_class(self):
|
||||||
'''
|
'''
|
||||||
|
@ -230,6 +241,14 @@ class FormsetTests(TestCase):
|
||||||
self.assertTrue(isinstance(form.errors, ErrorDict))
|
self.assertTrue(isinstance(form.errors, ErrorDict))
|
||||||
self.assertTrue(isinstance(form.non_field_errors(), ErrorList))
|
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):
|
class CustomWidget(forms.CharField):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue