Fixed #27119 -- Cached BaseFormSet.management_form property

Thanks Tim Graham for the review.
This commit is contained in:
Claude Paroz 2016-12-01 20:17:25 +01:00 committed by GitHub
parent dd2e4d7b5d
commit d49551bc26
2 changed files with 31 additions and 4 deletions

View File

@ -87,7 +87,7 @@ class BaseFormSet(object):
def __nonzero__(self): # Python 2 compatibility
return type(self).__bool__(self)
@property
@cached_property
def management_form(self):
"""Returns the ManagementForm instance for this FormSet."""
if self.is_bound:

View File

@ -2,14 +2,15 @@
from __future__ import unicode_literals
import datetime
from collections import Counter
from django.forms import (
CharField, DateField, FileField, Form, IntegerField, SplitDateTimeField,
ValidationError, formsets,
BaseForm, CharField, DateField, FileField, Form, IntegerField,
SplitDateTimeField, ValidationError, formsets,
)
from django.forms.formsets import BaseFormSet, formset_factory
from django.forms.utils import ErrorList
from django.test import SimpleTestCase
from django.test import SimpleTestCase, mock
from django.utils.encoding import force_text
@ -165,6 +166,32 @@ class FormsFormsetTestCase(SimpleTestCase):
self.assertFalse(formset.is_valid())
self.assertEqual(formset.errors, [{'votes': ['This field is required.']}])
def test_formset_validation_count(self):
"""
A formset's ManagementForm is validated once per FormSet.is_valid()
call and each form of the formset is cleaned once.
"""
def make_method_counter(func):
"""Add a counter to func for the number of times it's called."""
counter = Counter()
counter.call_count = 0
def mocked_func(*args, **kwargs):
counter.call_count += 1
return func(*args, **kwargs)
return mocked_func, counter
mocked_is_valid, is_valid_counter = make_method_counter(formsets.ManagementForm.is_valid)
mocked_full_clean, full_clean_counter = make_method_counter(BaseForm.full_clean)
formset = self.make_choiceformset([('Calexico', '100'), ('Any1', '42'), ('Any2', '101')])
with mock.patch('django.forms.formsets.ManagementForm.is_valid', mocked_is_valid), \
mock.patch('django.forms.forms.BaseForm.full_clean', mocked_full_clean):
self.assertTrue(formset.is_valid())
self.assertEqual(is_valid_counter.call_count, 1)
self.assertEqual(full_clean_counter.call_count, 4)
def test_formset_has_changed(self):
# FormSet instances has_changed method will be True if any data is
# passed to his forms, even if the formset didn't validate