diff --git a/django/forms/formsets.py b/django/forms/formsets.py
index fd98c43..e3a729b 100644
|
a
|
b
|
from django.forms.fields import IntegerField, BooleanField
|
| 6 | 6 | from django.forms.util import ErrorList |
| 7 | 7 | from django.forms.widgets import Media, HiddenInput |
| 8 | 8 | from django.utils.encoding import python_2_unicode_compatible |
| | 9 | from django.utils.functional import cached_property |
| 9 | 10 | from django.utils.safestring import mark_safe |
| 10 | 11 | from django.utils import six |
| 11 | 12 | from django.utils.six.moves import xrange |
| … |
… |
class BaseFormSet(object):
|
| 55 | 56 | self.error_class = error_class |
| 56 | 57 | self._errors = None |
| 57 | 58 | self._non_form_errors = None |
| 58 | | # construct the forms in the formset |
| 59 | | self._construct_forms() |
| 60 | 59 | |
| 61 | 60 | def __str__(self): |
| 62 | 61 | return self.as_table() |
| … |
… |
class BaseFormSet(object):
|
| 122 | 121 | initial_forms = len(self.initial) if self.initial else 0 |
| 123 | 122 | return initial_forms |
| 124 | 123 | |
| 125 | | def _construct_forms(self): |
| 126 | | # instantiate all the forms and put them in self.forms |
| 127 | | self.forms = [] |
| | 124 | @cached_property |
| | 125 | def forms(self): |
| | 126 | """ |
| | 127 | Instantiate forms at first property access. |
| | 128 | """ |
| 128 | 129 | # DoS protection is included in total_form_count() |
| 129 | | for i in xrange(self.total_form_count()): |
| 130 | | self.forms.append(self._construct_form(i)) |
| | 130 | forms = [self._construct_form(i) for i in xrange(self.total_form_count())] |
| | 131 | return forms |
| 131 | 132 | |
| 132 | 133 | def _construct_form(self, i, **kwargs): |
| 133 | 134 | """ |
diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py
index 1e9e7db3..eca3f7d 100644
|
a
|
b
|
ArticleFormSet = formset_factory(ArticleForm)
|
| 1070 | 1070 | |
| 1071 | 1071 | class TestIsBoundBehavior(TestCase): |
| 1072 | 1072 | def test_no_data_raises_validation_error(self): |
| 1073 | | self.assertRaises(ValidationError, ArticleFormSet, {}) |
| | 1073 | with self.assertRaises(ValidationError): |
| | 1074 | ArticleFormSet({}).is_valid() |
| 1074 | 1075 | |
| 1075 | 1076 | def test_with_management_data_attrs_work_fine(self): |
| 1076 | 1077 | data = { |
diff --git a/tests/model_formsets/tests.py b/tests/model_formsets/tests.py
index 03cd3b0..4a8b363 100644
|
a
|
b
|
from decimal import Decimal
|
| 8 | 8 | from django import forms |
| 9 | 9 | from django.db import models |
| 10 | 10 | from django.forms.models import (_get_foreign_key, inlineformset_factory, |
| 11 | | modelformset_factory) |
| | 11 | modelformset_factory, BaseModelFormSet) |
| 12 | 12 | from django.test import TestCase, skipUnlessDBFeature |
| 13 | 13 | from django.utils import six |
| 14 | 14 | |
| … |
… |
class ModelFormsetTest(TestCase):
|
| 386 | 386 | formset = PostFormSet() |
| 387 | 387 | self.assertFalse("subtitle" in formset.forms[0].fields) |
| 388 | 388 | |
| | 389 | def test_custom_queryset_init(self): |
| | 390 | """ |
| | 391 | Test that a queryset can be overriden in the __init__ method. |
| | 392 | https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#changing-the-queryset |
| | 393 | """ |
| | 394 | author1 = Author.objects.create(name='Charles Baudelaire') |
| | 395 | author2 = Author.objects.create(name='Paul Verlaine') |
| | 396 | |
| | 397 | class BaseAuthorFormSet(BaseModelFormSet): |
| | 398 | def __init__(self, *args, **kwargs): |
| | 399 | super(BaseAuthorFormSet, self).__init__(*args, **kwargs) |
| | 400 | self.queryset = Author.objects.filter(name__startswith='Charles') |
| | 401 | |
| | 402 | AuthorFormSet = modelformset_factory(Author, formset=BaseAuthorFormSet) |
| | 403 | formset = AuthorFormSet() |
| | 404 | self.assertEqual(len(formset.get_queryset()), 1) |
| | 405 | |
| 389 | 406 | def test_model_inheritance(self): |
| 390 | 407 | BetterAuthorFormSet = modelformset_factory(BetterAuthor, fields="__all__") |
| 391 | 408 | formset = BetterAuthorFormSet() |