Commit 4ef10f24 authored by Anders Steinlein's avatar Anders Steinlein Committed by Tim Graham
Browse files

Fixed #17642 -- Added min_num support to modelformsets, inlines, and the admin.

Thanks Stephen Burrows for work on the patch as well.

Forwardport of 2914f669 from stable/1.7.x
parent 860d31ac
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -850,6 +850,7 @@ class InlineModelAdminChecks(BaseModelAdminChecks):
        errors.extend(self._check_exclude_of_parent_model(cls, parent_model))
        errors.extend(self._check_extra(cls))
        errors.extend(self._check_max_num(cls))
        errors.extend(self._check_min_num(cls))
        errors.extend(self._check_formset(cls))
        return errors

@@ -909,12 +910,22 @@ class InlineModelAdminChecks(BaseModelAdminChecks):
        else:
            return []

    def _check_min_num(self, cls):
        """ Check that min_num is an integer. """

        if cls.min_num is None:
            return []
        elif not isinstance(cls.min_num, int):
            return must_be('an integer', option='min_num', obj=cls, id='admin.E205')
        else:
            return []

    def _check_formset(self, cls):
        """ Check formset is a subclass of BaseModelFormSet. """

        if not issubclass(cls.formset, BaseModelFormSet):
            return must_inherit_from(parent='BaseModelFormSet', option='formset',
                                     obj=cls, id='admin.E205')
                                     obj=cls, id='admin.E206')
        else:
            return []

+6 −0
Original line number Diff line number Diff line
@@ -1706,6 +1706,7 @@ class InlineModelAdmin(BaseModelAdmin):
    fk_name = None
    formset = BaseInlineFormSet
    extra = 3
    min_num = None
    max_num = None
    template = None
    verbose_name = None
@@ -1738,6 +1739,10 @@ class InlineModelAdmin(BaseModelAdmin):
        """Hook for customizing the number of extra inline forms."""
        return self.extra

    def get_min_num(self, request, obj=None, **kwargs):
        """Hook for customizing the min number of inline forms."""
        return self.min_num

    def get_max_num(self, request, obj=None, **kwargs):
        """Hook for customizing the max number of extra inline forms."""
        return self.max_num
@@ -1769,6 +1774,7 @@ class InlineModelAdmin(BaseModelAdmin):
            "exclude": exclude,
            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
            "extra": self.get_extra(request, obj, **kwargs),
            "min_num": self.get_min_num(request, obj, **kwargs),
            "max_num": self.get_max_num(request, obj, **kwargs),
            "can_delete": can_delete,
        }
+1 −0
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ class GenericInlineModelAdmin(InlineModelAdmin):
            "can_delete": can_delete,
            "can_order": False,
            "fields": fields,
            "min_num": self.min_num,
            "max_num": self.max_num,
            "exclude": exclude
        }
+5 −4
Original line number Diff line number Diff line
@@ -56,9 +56,9 @@ def generic_inlineformset_factory(model, form=ModelForm,
                                  ct_field="content_type", fk_field="object_id",
                                  fields=None, exclude=None,
                                  extra=3, can_order=False, can_delete=True,
                                  max_num=None,
                                  formfield_callback=None, validate_max=False,
                                  for_concrete_model=True):
                                  max_num=None, formfield_callback=None,
                                  validate_max=False, for_concrete_model=True,
                                  min_num=None, validate_min=False):
    """
    Returns a ``GenericInlineFormSet`` for the given kwargs.

@@ -81,7 +81,8 @@ def generic_inlineformset_factory(model, form=ModelForm,
                                   formset=formset,
                                   extra=extra, can_delete=can_delete, can_order=can_order,
                                   fields=fields, exclude=exclude, max_num=max_num,
                                   validate_max=validate_max)
                                   validate_max=validate_max, min_num=min_num,
                                   validate_min=validate_min)
    FormSet.ct_field = ct_field
    FormSet.ct_fk_field = fk_field
    FormSet.for_concrete_model = for_concrete_model
+8 −4
Original line number Diff line number Diff line
@@ -805,7 +805,8 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
                         formset=BaseModelFormSet, extra=1, can_delete=False,
                         can_order=False, max_num=None, fields=None, exclude=None,
                         widgets=None, validate_max=False, localized_fields=None,
                         labels=None, help_texts=None, error_messages=None):
                         labels=None, help_texts=None, error_messages=None,
                         min_num=None, validate_min=False):
    """
    Returns a FormSet class for the given Django model class.
    """
@@ -823,9 +824,9 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
                             formfield_callback=formfield_callback,
                             widgets=widgets, localized_fields=localized_fields,
                             labels=labels, help_texts=help_texts, error_messages=error_messages)
    FormSet = formset_factory(form, formset, extra=extra, max_num=max_num,
    FormSet = formset_factory(form, formset, extra=extra, min_num=min_num, max_num=max_num,
                              can_order=can_order, can_delete=can_delete,
                              validate_max=validate_max)
                              validate_min=validate_min, validate_max=validate_max)
    FormSet.model = model
    return FormSet

@@ -969,7 +970,8 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
                          fields=None, exclude=None, extra=3, can_order=False,
                          can_delete=True, max_num=None, formfield_callback=None,
                          widgets=None, validate_max=False, localized_fields=None,
                          labels=None, help_texts=None, error_messages=None):
                          labels=None, help_texts=None, error_messages=None,
                          min_num=None, validate_min=False):
    """
    Returns an ``InlineFormSet`` for the given kwargs.

@@ -989,8 +991,10 @@ def inlineformset_factory(parent_model, model, form=ModelForm,
        'can_order': can_order,
        'fields': fields,
        'exclude': exclude,
        'min_num': min_num,
        'max_num': max_num,
        'widgets': widgets,
        'validate_min': validate_min,
        'validate_max': validate_max,
        'localized_fields': localized_fields,
        'labels': labels,
Loading