Code

Ticket #9532: 9532_2.patch

File 9532_2.patch, 11.7 KB (added by michal@…, 2 years ago)

Removed maxDiff = None from test case

  • django/forms/formsets.py

    diff --git a/django/forms/formsets.py b/django/forms/formsets.py
    index dcd2f01..0c53006 100644
    a b __all__ = ('BaseFormSet', 'all_valid') 
    1616TOTAL_FORM_COUNT = 'TOTAL_FORMS' 
    1717INITIAL_FORM_COUNT = 'INITIAL_FORMS' 
    1818MAX_NUM_FORM_COUNT = 'MAX_NUM_FORMS' 
     19MIN_NUM_FORM_COUNT = 'MIN_NUM_FORMS' 
    1920ORDERING_FIELD_NAME = 'ORDER' 
    2021DELETION_FIELD_NAME = 'DELETE' 
    2122 
    class ManagementForm(Form): 
    2930        self.base_fields[TOTAL_FORM_COUNT] = IntegerField(widget=HiddenInput) 
    3031        self.base_fields[INITIAL_FORM_COUNT] = IntegerField(widget=HiddenInput) 
    3132        self.base_fields[MAX_NUM_FORM_COUNT] = IntegerField(required=False, widget=HiddenInput) 
     33        self.base_fields[MIN_NUM_FORM_COUNT] = IntegerField(required=False, widget=HiddenInput) 
    3234        super(ManagementForm, self).__init__(*args, **kwargs) 
    3335 
    3436class BaseFormSet(StrAndUnicode): 
    class BaseFormSet(StrAndUnicode): 
    7779            form = ManagementForm(auto_id=self.auto_id, prefix=self.prefix, initial={ 
    7880                TOTAL_FORM_COUNT: self.total_form_count(), 
    7981                INITIAL_FORM_COUNT: self.initial_form_count(), 
    80                 MAX_NUM_FORM_COUNT: self.max_num 
     82                MAX_NUM_FORM_COUNT: self.max_num, 
     83                MIN_NUM_FORM_COUNT: self.min_num 
    8184            }) 
    8285        return form 
    8386    management_form = property(_management_form) 
    class BaseFormSet(StrAndUnicode): 
    9598                total_forms = initial_forms 
    9699            elif total_forms > self.max_num >= 0: 
    97100                total_forms = self.max_num 
     101 
     102            total_forms = max(total_forms, self.min_num) 
     103 
    98104        return total_forms 
    99105 
    100106    def initial_form_count(self): 
    class BaseFormSet(StrAndUnicode): 
    358364        return mark_safe(u'\n'.join([unicode(self.management_form), forms])) 
    359365 
    360366def formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, 
    361                     can_delete=False, max_num=None): 
     367                    can_delete=False, max_num=None, min_num=None): 
    362368    """Return a FormSet for the given form class.""" 
     369    if not None in (max_num, min_num) and max_num < min_num: 
     370        raise ValueError('max_num cannot be smaller than min_num') 
     371 
    363372    attrs = {'form': form, 'extra': extra, 
    364373             'can_order': can_order, 'can_delete': can_delete, 
    365              'max_num': max_num} 
     374             'max_num': max_num, 'min_num': min_num } 
    366375    return type(form.__name__ + 'FormSet', (formset,), attrs) 
    367376 
     377 
    368378def all_valid(formsets): 
    369379    """Returns true if every formset in formsets is valid.""" 
    370380    valid = True 
  • docs/topics/forms/formsets.txt

    diff --git a/docs/topics/forms/formsets.txt b/docs/topics/forms/formsets.txt
    index b524c24..9a91182 100644
    a b A ``max_num`` value of ``None`` (the default) puts no limit on the number of 
    112112forms displayed. Please note that the default value of ``max_num`` was changed 
    113113from ``0`` to ``None`` in version 1.2 to allow ``0`` as a valid value. 
    114114 
     115.. _formsets-min-num: 
     116 
     117Ensuring the minimum number of forms 
     118------------------------------------ 
     119 
     120The ``min_num`` parameter to ``formset_factory`` gives you the ability to make 
     121sure that at least a certain number of forms will be displayed:: 
     122 
     123    >>> ArticleFormSet = formset_factory(ArticleForm, min_num=2) 
     124    >>> formset = ArticleFormset(initial=[ 
     125    ...     {'title': u'Django is now open source', 
     126    ...      'pub_date': datetime.date.today(),} 
     127    ... ]) 
     128 
     129    >>> for form in formset: 
     130    ...     print form.as_table() 
     131    <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr> 
     132    <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2012-04-02" id="id_form-0-pub_date" /></td></tr> 
     133    <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr> 
     134    <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr> 
     135 
     136.. versionchanged:: 1.4 
     137 
     138If the value of ``min_num`` is greater than the number of elements that would 
     139be displayed normally (including extra forms), additional blank forms will be 
     140added to the formset. 
     141 
     142If ``min_num`` is greater than ``max_num``, ``ValueError`` will be raised by 
     143``formset_factory`` function. 
     144 
    115145Formset validation 
    116146------------------ 
    117147 
  • tests/regressiontests/forms/tests/formsets.py

    diff --git a/tests/regressiontests/forms/tests/formsets.py b/tests/regressiontests/forms/tests/formsets.py
    index 05ef978..add9254 100644
    a b class FormsFormsetTestCase(TestCase): 
    4747        # for adding data. By default, it displays 1 blank form. It can display more, 
    4848        # but we'll look at how to do so later. 
    4949        formset = ChoiceFormSet(auto_id=False, prefix='choices') 
    50         self.assertHTMLEqual(str(formset), """<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" /> 
     50        self.assertHTMLEqual(str(formset), """<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" /><input type="hidden" name="choices-MIN_NUM_FORMS" /> 
    5151<tr><th>Choice:</th><td><input type="text" name="choices-0-choice" /></td></tr> 
    5252<tr><th>Votes:</th><td><input type="text" name="choices-0-votes" /></td></tr>""") 
    5353 
    class FormsFormsetTestCase(TestCase): 
    646646        self.assertTrue(formset.is_valid()) 
    647647        self.assertEqual(formset.non_form_errors(), []) 
    648648 
     649    def test_appending_min_forms(self): 
     650        # Ensuring the minimum number of forms ######################################## 
     651        # Base case for min_num. 
     652 
     653        # When not passed, min_num will take its default value of None, i.e. no required 
     654        # forms, only controller by the value of the extra parameter. 
     655 
     656        initial = [ dict(name='Pony') ] 
     657        LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=0, min_num=1) 
     658        formset = LimitedFavoriteDrinkFormSet() 
     659 
     660        self.assertHTMLEqual('\n'.join(str(form) for form in formset.forms), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" id="id_form-0-name" /></td></tr>""") 
     661 
     662        LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=0, min_num=2) 
     663        formset = LimitedFavoriteDrinkFormSet(initial=initial) 
     664 
     665        self.assertHTMLEqual('\n'.join(str(form) for form in formset.forms), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" id="id_form-0-name" value="Pony" /></td></tr> 
     666<tr><th><label for="id_form-1-name">Name:</label></th><td><input type="text" name="form-1-name" id="id_form-1-name" /></td></tr>""") 
     667 
     668        LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=0, min_num=1) 
     669        formset = LimitedFavoriteDrinkFormSet(initial=initial) 
     670 
     671        self.assertHTMLEqual('\n'.join(str(form) for form in formset.forms), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" id="id_form-0-name" value="Pony" /></td></tr>""") 
     672 
     673        LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, min_num=1) 
     674        formset = LimitedFavoriteDrinkFormSet(initial=initial) 
     675 
     676        self.assertHTMLEqual('\n'.join(str(form) for form in formset.forms), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" id="id_form-0-name" value="Pony" /></td></tr> 
     677<tr><th><label for="id_form-1-name">Name:</label></th><td><input type="text" name="form-1-name" id="id_form-1-name" /></td></tr>""") 
     678 
     679        LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=1, min_num=1, max_num=1) 
     680        formset = LimitedFavoriteDrinkFormSet(initial=initial) 
     681 
     682        self.assertHTMLEqual('\n'.join(str(form) for form in formset.forms), """<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" id="id_form-0-name" value="Pony" /></td></tr>""") 
     683 
     684    def test_formset_management_form_contains_min_num(self): 
     685        LimitedFavoriteDrinkFormSet = formset_factory(FavoriteDrinkForm, extra=0, min_num=1) 
     686        formset = LimitedFavoriteDrinkFormSet() 
     687 
     688        self.assertHTMLEqual(str(formset), """<input type="hidden" id="id_form-TOTAL_FORMS" name="form-TOTAL_FORMS" value="1" /><input type="hidden" id="id_form-INITIAL_FORMS" name="form-INITIAL_FORMS" value="0" /><input type="hidden" id="id_form-MAX_NUM_FORMS" name="form-MAX_NUM_FORMS" /><input type="hidden" id="id_form-MIN_NUM_FORMS" name="form-MIN_NUM_FORMS" value="1" /> 
     689<tr><th><label for="id_form-0-name">Name:</label></th><td><input type="text" name="form-0-name" id="id_form-0-name" /></td></tr>""") 
     690 
     691    def test_wrong_min_forms(self): 
     692        self.assertRaises(ValueError, formset_factory, FavoriteDrinkForm, min_num=2, max_num=1) 
     693 
    649694    def test_limiting_max_forms(self): 
    650695        # Limiting the maximum number of forms ######################################## 
    651696        # Base case for max_num. 
    ChoiceFormSet = formset_factory(Choice) 
    862907class FormsetAsFooTests(TestCase): 
    863908    def test_as_table(self): 
    864909        formset = ChoiceFormSet(data, auto_id=False, prefix='choices') 
    865         self.assertHTMLEqual(formset.as_table(),"""<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="0" /> 
     910        self.assertHTMLEqual(formset.as_table(),"""<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="0" /><input type="hidden" name="choices-MIN_NUM_FORMS" /> 
    866911<tr><th>Choice:</th><td><input type="text" name="choices-0-choice" value="Calexico" /></td></tr> 
    867912<tr><th>Votes:</th><td><input type="text" name="choices-0-votes" value="100" /></td></tr>""") 
    868913 
    869914    def test_as_p(self): 
    870915        formset = ChoiceFormSet(data, auto_id=False, prefix='choices') 
    871         self.assertHTMLEqual(formset.as_p(),"""<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="0" /> 
     916        self.assertHTMLEqual(formset.as_p(),"""<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="0" /><input type="hidden" name="choices-MIN_NUM_FORMS" /> 
    872917<p>Choice: <input type="text" name="choices-0-choice" value="Calexico" /></p> 
    873918<p>Votes: <input type="text" name="choices-0-votes" value="100" /></p>""") 
    874919 
    875920    def test_as_ul(self): 
    876921        formset = ChoiceFormSet(data, auto_id=False, prefix='choices') 
    877         self.assertHTMLEqual(formset.as_ul(),"""<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="0" /> 
     922        self.assertHTMLEqual(formset.as_ul(),"""<input type="hidden" name="choices-TOTAL_FORMS" value="1" /><input type="hidden" name="choices-INITIAL_FORMS" value="0" /><input type="hidden" name="choices-MAX_NUM_FORMS" value="0" /><input type="hidden" name="choices-MIN_NUM_FORMS" /> 
    878923<li>Choice: <input type="text" name="choices-0-choice" value="Calexico" /></li> 
    879924<li>Votes: <input type="text" name="choices-0-votes" value="100" /></li>""") 
    880925