Ticket #17642: 17642-v2.diff

File 17642-v2.diff, 10.5 KB (added by Anders Steinlein, 11 years ago)

Updated patch.

  • django/contrib/admin/options.py

    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index b4fa54a..1b75600 100644
    a b class InlineModelAdmin(BaseModelAdmin):  
    17061706    fk_name = None
    17071707    formset = BaseInlineFormSet
    17081708    extra = 3
     1709    min_num = None
    17091710    max_num = None
    17101711    template = None
    17111712    verbose_name = None
    class InlineModelAdmin(BaseModelAdmin):  
    17381739        """Hook for customizing the number of extra inline forms."""
    17391740        return self.extra
    17401741
     1742    def get_min_num(self, request, obj=None, **kwargs):
     1743        """Hook for customizing the min number of inline forms."""
     1744        return self.min_num
     1745
    17411746    def get_max_num(self, request, obj=None, **kwargs):
    17421747        """Hook for customizing the max number of extra inline forms."""
    17431748        return self.max_num
    class InlineModelAdmin(BaseModelAdmin):  
    17691774            "exclude": exclude,
    17701775            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
    17711776            "extra": self.get_extra(request, obj, **kwargs),
     1777            "min_num": self.get_min_num(request, obj, **kwargs),
    17721778            "max_num": self.get_max_num(request, obj, **kwargs),
    17731779            "can_delete": can_delete,
    17741780        }
  • django/contrib/contenttypes/admin.py

    diff --git a/django/contrib/contenttypes/admin.py b/django/contrib/contenttypes/admin.py
    index c67fbca..9fa3af6 100644
    a b class GenericInlineModelAdmin(InlineModelAdmin):  
    4141            "can_delete": can_delete,
    4242            "can_order": False,
    4343            "fields": fields,
     44            "min_num": self.min_num,
    4445            "max_num": self.max_num,
    4546            "exclude": exclude
    4647        }
  • django/contrib/contenttypes/forms.py

    diff --git a/django/contrib/contenttypes/forms.py b/django/contrib/contenttypes/forms.py
    index 33df752..f962793 100644
    a b def generic_inlineformset_factory(model, form=ModelForm,  
    5656                                  ct_field="content_type", fk_field="object_id",
    5757                                  fields=None, exclude=None,
    5858                                  extra=3, can_order=False, can_delete=True,
    59                                   max_num=None,
    60                                   formfield_callback=None, validate_max=False,
    61                                   for_concrete_model=True):
     59                                  max_num=None, validate_max=False,
     60                                  min_num=None, validate_min=False,
     61                                  formfield_callback=None, for_concrete_model=True):
    6262    """
    6363    Returns a ``GenericInlineFormSet`` for the given kwargs.
    6464
    def generic_inlineformset_factory(model, form=ModelForm,  
    8181                                   formset=formset,
    8282                                   extra=extra, can_delete=can_delete, can_order=can_order,
    8383                                   fields=fields, exclude=exclude, max_num=max_num,
    84                                    validate_max=validate_max)
     84                                   validate_max=validate_max, min_num=min_num,
     85                                   validate_min=validate_min)
    8586    FormSet.ct_field = ct_field
    8687    FormSet.ct_fk_field = fk_field
    8788    FormSet.for_concrete_model = for_concrete_model
  • django/forms/models.py

    diff --git a/django/forms/models.py b/django/forms/models.py
    index a0b47e6..b0a3c36 100644
    a b class BaseModelFormSet(BaseFormSet):  
    806806
    807807def modelformset_factory(model, form=ModelForm, formfield_callback=None,
    808808                         formset=BaseModelFormSet, extra=1, can_delete=False,
    809                          can_order=False, max_num=None, fields=None, exclude=None,
    810                          widgets=None, validate_max=False, localized_fields=None,
     809                         can_order=False, min_num=None, max_num=None, fields=None,exclude=None,
     810                         widgets=None, validate_min=False, validate_max=False, localized_fields=None,
    811811                         labels=None, help_texts=None, error_messages=None):
    812812    """
    813813    Returns a FormSet class for the given Django model class.
    def modelformset_factory(model, form=ModelForm, formfield_callback=None,  
    831831                             formfield_callback=formfield_callback,
    832832                             widgets=widgets, localized_fields=localized_fields,
    833833                             labels=labels, help_texts=help_texts, error_messages=error_messages)
    834     FormSet = formset_factory(form, formset, extra=extra, max_num=max_num,
     834    FormSet = formset_factory(form, formset, extra=extra, min_num=min_num, max_num=max_num,
    835835                              can_order=can_order, can_delete=can_delete,
    836                               validate_max=validate_max)
     836                              validate_min=validate_min, validate_max=validate_max)
    837837    FormSet.model = model
    838838    return FormSet
    839839
    def _get_foreign_key(parent_model, model, fk_name=None, can_fail=False):  
    975975def inlineformset_factory(parent_model, model, form=ModelForm,
    976976                          formset=BaseInlineFormSet, fk_name=None,
    977977                          fields=None, exclude=None, extra=3, can_order=False,
    978                           can_delete=True, max_num=None, formfield_callback=None,
    979                           widgets=None, validate_max=False, localized_fields=None,
     978                          can_delete=True, min_num=None, max_num=None, formfield_callback=None,
     979                          widgets=None, validate_min=False, validate_max=False, localized_fields=None,
    980980                          labels=None, help_texts=None, error_messages=None):
    981981    """
    982982    Returns an ``InlineFormSet`` for the given kwargs.
    def inlineformset_factory(parent_model, model, form=ModelForm,  
    997997        'can_order': can_order,
    998998        'fields': fields,
    999999        'exclude': exclude,
     1000        'min_num': min_num,
    10001001        'max_num': max_num,
    10011002        'widgets': widgets,
     1003        'validate_min': validate_min,
    10021004        'validate_max': validate_max,
    10031005        'localized_fields': localized_fields,
    10041006        'labels': labels,
  • docs/ref/contrib/admin/index.txt

    diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
    index e160926..63c1fa5 100644
    a b The ``InlineModelAdmin`` class adds:  
    19931993    :meth:`InlineModelAdmin.get_max_num` also allows you to customize the
    19941994    maximum number of extra forms.
    19951995
     1996    .. _ref-contrib-admin-inline-min-num:
     1997
     1998.. attribute:: InlineModelAdmin.min_num
     1999
     2000    This controls the minimum number of forms to show in the inline.
     2001    See :ref:`model-formsets-min-num` for more information.
     2002
     2003    .. versionadded:: 1.7
     2004
     2005    :meth:`InlineModelAdmin.get_min_num` also allows you to customize the
     2006    maximum number of extra forms.
     2007
    19962008.. attribute:: InlineModelAdmin.raw_id_fields
    19972009
    19982010    By default, Django's admin uses a select-box interface (<select>) for
    The ``InlineModelAdmin`` class adds:  
    20732085                    return max_num - 5
    20742086                return max_num
    20752087
     2088.. method:: InlineModelAdmin.get_min_num(request, obj=None, **kwargs)
     2089
     2090    .. versionadded:: 1.7
     2091
     2092    Returns the minimum number of inline forms to use. By default,
     2093    returns the :attr:`InlineModelAdmin.min_num` attribute.
     2094
     2095    Override this method to programmatically determine the minimum number of
     2096    inline forms. For example, this may be based on the model instance
     2097    (passed as the keyword argument ``obj``).
    20762098
    20772099Working with a model with two or more foreign keys to the same parent model
    20782100---------------------------------------------------------------------------
  • tests/admin_inlines/admin.py

    diff --git a/tests/admin_inlines/admin.py b/tests/admin_inlines/admin.py
    index b46a045..a9ea346 100644
    a b from .models import (  
    88    Inner4Tabular, NonAutoPKBook, Novel, ParentModelWithCustomPk, Poll,
    99    Profile, ProfileCollection, Question, ReadOnlyInline, ShoppingWeakness,
    1010    Sighting, SomeChildModel, SomeParentModel, SottoCapo, Title,
    11     TitleCollection,
     11    TitleCollection, Holder5, Inner5
    1212)
    1313
    1414site = admin.AdminSite(name="admin")
    class BinaryTreeAdmin(admin.TabularInline):  
    171171        return max_num
    172172
    173173
     174# inline and admin for testing min_num
     175
     176class InnerMinNumInline(admin.TabularInline):
     177    model = Inner5
     178    min_num = 2
     179    extra = 2
     180
     181
     182class HolderMinNumAdmin(admin.ModelAdmin):
     183    inlines = [InnerMinNumInline]
     184
     185
    174186# admin for #19524
    175187class SightingInline(admin.TabularInline):
    176188    model = Sighting
    site.register(ParentModelWithCustomPk, inlines=[ChildModel1Inline, ChildModel2In  
    212224site.register(BinaryTree, inlines=[BinaryTreeAdmin])
    213225site.register(ExtraTerrestrial, inlines=[SightingInline])
    214226site.register(SomeParentModel, inlines=[SomeChildModelInline])
     227site.register(Holder5, HolderMinNumAdmin)
  • tests/admin_inlines/models.py

    diff --git a/tests/admin_inlines/models.py b/tests/admin_inlines/models.py
    index 0ad59a0..b824728 100644
    a b class Inner4Tabular(models.Model):  
    114114    dummy = models.IntegerField(help_text="Awesome tabular help text is awesome.")
    115115    holder = models.ForeignKey(Holder4)
    116116
     117
     118# Models for min_num
     119
     120class Holder5(models.Model):
     121    dummy = models.IntegerField()
     122
     123
     124class Inner5(models.Model):
     125    dummy = models.IntegerField()
     126    holder = models.ForeignKey(Holder5)
     127
     128
    117129# Models for #12749
    118130
    119131
  • tests/admin_inlines/tests.py

    diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py
    index 2f3fdfd..feb4225 100644
    a b class TestInline(TestCase):  
    221221        self.assertContains(response, max_forms_input % 2)
    222222        self.assertContains(response, total_forms_hidden)
    223223
     224    def test_min_num(self):
     225        """
     226        Ensure that min_num + extra dermine number of inlines.
     227        """
     228        min_forms = '<input id="id_inner5_set-MIN_NUM_FORMS" name="inner5_set-MIN_NUM_FORMS" type="hidden" value="2" />'
     229        total_forms = '<input id="id_inner5_set-TOTAL_FORMS" name="inner5_set-TOTAL_FORMS" type="hidden" value="4" />'
     230
     231        response = self.client.get('/admin/admin_inlines/holder5/add/')
     232        self.assertContains(response, min_forms)
     233        self.assertContains(response, total_forms)
     234
    224235    def test_inline_nonauto_noneditable_pk(self):
    225236        response = self.client.get('/admin/admin_inlines/author/add/')
    226237        self.assertContains(response,
Back to Top