Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #18388 - Added InlineModelAdmin.get_max_num hook.

Thanks d.willy.c.c@ for the suggestion and Melevir and Areski Belaid for work
on the patch.
  • Loading branch information...
commit 61524b09cfa3b51643d0e79cbf0e1e08ede357ae 1 parent 07a73a2
Tim Graham authored June 01, 2013
6  django/contrib/admin/options.py
@@ -1516,6 +1516,10 @@ def get_extra(self, request, obj=None, **kwargs):
1516 1516
         """Hook for customizing the number of extra inline forms."""
1517 1517
         return self.extra
1518 1518
 
  1519
+    def get_max_num(self, request, obj=None, **kwargs):
  1520
+        """Hook for customizing the max number of extra inline forms."""
  1521
+        return self.max_num
  1522
+
1519 1523
     def get_formset(self, request, obj=None, **kwargs):
1520 1524
         """Returns a BaseInlineFormSet class for use in admin add/change views."""
1521 1525
         if 'fields' in kwargs:
@@ -1543,7 +1547,7 @@ def get_formset(self, request, obj=None, **kwargs):
1543 1547
             "exclude": exclude,
1544 1548
             "formfield_callback": partial(self.formfield_for_dbfield, request=request),
1545 1549
             "extra": self.get_extra(request, obj, **kwargs),
1546  
-            "max_num": self.max_num,
  1550
+            "max_num": self.get_max_num(request, obj, **kwargs),
1547 1551
             "can_delete": can_delete,
1548 1552
         }
1549 1553
 
26  docs/ref/contrib/admin/index.txt
@@ -1728,6 +1728,11 @@ The ``InlineModelAdmin`` class adds:
1728 1728
     doesn't directly correlate to the number of objects, but can if the value
1729 1729
     is small enough. See :ref:`model-formsets-max-num` for more information.
1730 1730
 
  1731
+    .. versionadded:: 1.6
  1732
+
  1733
+    :meth:`InlineModelAdmin.get_max_num` also allows you to customize the
  1734
+    maximum number of extra forms.
  1735
+
1731 1736
 .. attribute:: InlineModelAdmin.raw_id_fields
1732 1737
 
1733 1738
     By default, Django's admin uses a select-box interface (<select>) for
@@ -1787,6 +1792,27 @@ The ``InlineModelAdmin`` class adds:
1787 1792
                     return extra - obj.binarytree_set.count()
1788 1793
                 return extra
1789 1794
 
  1795
+.. method:: InlineModelAdmin.get_max_num(self, request, obj=None, **kwargs)
  1796
+
  1797
+    .. versionadded:: 1.6
  1798
+
  1799
+    Returns the maximum number of extra inline forms to use. By default,
  1800
+    returns the :attr:`InlineModelAdmin.max_num` attribute.
  1801
+
  1802
+    Override this method to programmatically determine the maximum number of
  1803
+    inline forms. For example, this may be based on the model instance
  1804
+    (passed as the keyword argument ``obj``)::
  1805
+
  1806
+        class BinaryTreeAdmin(admin.TabularInline):
  1807
+            model = BinaryTree
  1808
+
  1809
+            def get_max_num(self, request, obj=None, **kwargs):
  1810
+                max_num = 10
  1811
+                if obj.parent:
  1812
+                    return max_num - 5
  1813
+                return max_num
  1814
+
  1815
+
1790 1816
 Working with a model with two or more foreign keys to the same parent model
1791 1817
 ---------------------------------------------------------------------------
1792 1818
 
5  docs/releases/1.6.txt
@@ -292,9 +292,10 @@ Minor features
292 292
   :meth:`~django.db.models.query.QuerySet.select_related` can be cleared using
293 293
   ``select_related(None)``.
294 294
 
295  
-* The :meth:`~django.contrib.admin.InlineModelAdmin.get_extra` method on
  295
+* The :meth:`~django.contrib.admin.InlineModelAdmin.get_extra` and
  296
+  :meth:`~django.contrib.admin.InlineModelAdmin.get_max_num` methods on
296 297
   :class:`~django.contrib.admin.InlineModelAdmin` may be overridden to
297  
-  customize the number of extra inline forms.
  298
+  customize the extra and maximum number of inline forms.
298 299
 
299 300
 Backwards incompatible changes in 1.6
300 301
 =====================================
9  tests/admin_inlines/admin.py
@@ -129,7 +129,7 @@ class ChildModel1Inline(admin.TabularInline):
129 129
 class ChildModel2Inline(admin.StackedInline):
130 130
     model = ChildModel2
131 131
 
132  
-# admin for #19425
  132
+# admin for #19425 and #18388
133 133
 class BinaryTreeAdmin(admin.TabularInline):
134 134
     model = BinaryTree
135 135
 
@@ -137,9 +137,14 @@ def get_extra(self, request, obj=None, **kwargs):
137 137
         extra = 2
138 138
         if obj:
139 139
             return extra - obj.binarytree_set.count()
140  
-
141 140
         return extra
142 141
 
  142
+    def get_max_num(self, request, obj=None, **kwargs):
  143
+        max_num = 3
  144
+        if obj:
  145
+            return max_num - obj.binarytree_set.count()
  146
+        return max_num
  147
+
143 148
 # admin for #19524
144 149
 class SightingInline(admin.TabularInline):
145 150
     model = Sighting
6  tests/admin_inlines/tests.py
@@ -197,12 +197,18 @@ def test_custom_get_extra_form(self):
197 197
         bt_head = BinaryTree.objects.create(name="Tree Head")
198 198
         bt_child = BinaryTree.objects.create(name="First Child", parent=bt_head)
199 199
 
  200
+        # The maximum number of forms should respect 'get_max_num' on the
  201
+        # ModelAdmin
  202
+        max_forms_input = '<input id="id_binarytree_set-MAX_NUM_FORMS" name="binarytree_set-MAX_NUM_FORMS" type="hidden" value="%d" />'
200 203
         # The total number of forms will remain the same in either case
201 204
         total_forms_hidden = '<input id="id_binarytree_set-TOTAL_FORMS" name="binarytree_set-TOTAL_FORMS" type="hidden" value="2" />'
  205
+
202 206
         response = self.client.get('/admin/admin_inlines/binarytree/add/')
  207
+        self.assertContains(response, max_forms_input % 3)
203 208
         self.assertContains(response, total_forms_hidden)
204 209
 
205 210
         response = self.client.get("/admin/admin_inlines/binarytree/%d/" % bt_head.id)
  211
+        self.assertContains(response, max_forms_input % 2)
206 212
         self.assertContains(response, total_forms_hidden)
207 213
 
208 214
 

0 notes on commit 61524b0

Please sign in to comment.
Something went wrong with that request. Please try again.