Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #19425 - Added InlineModelAdmin.get_extra hook.

Thanks dave@ for the suggestion and Rohan Jain for the patch.
  • Loading branch information...
commit 36aecb12b850aeed173a8e524cacb3444f807785 1 parent 7902fd7
@timgraham timgraham authored
View
6 django/contrib/admin/options.py
@@ -1512,6 +1512,10 @@ def media(self):
js.extend(['SelectBox.js', 'SelectFilter2.js'])
return forms.Media(js=[static('admin/js/%s' % url) for url in js])
+ def get_extra(self, request, obj=None, **kwargs):
+ """Hook for customizing the number of extra inline forms."""
+ return self.extra
+
def get_formset(self, request, obj=None, **kwargs):
"""Returns a BaseInlineFormSet class for use in admin add/change views."""
if self.declared_fieldsets:
@@ -1538,7 +1542,7 @@ def get_formset(self, request, obj=None, **kwargs):
"fields": fields,
"exclude": exclude,
"formfield_callback": partial(self.formfield_for_dbfield, request=request),
- "extra": self.extra,
+ "extra": self.get_extra(request, obj, **kwargs),
"max_num": self.max_num,
"can_delete": can_delete,
}
View
25 docs/ref/contrib/admin/index.txt
@@ -1715,6 +1715,11 @@ The ``InlineModelAdmin`` class adds:
The dynamic link will not appear if the number of currently displayed forms
exceeds ``max_num``, or if the user does not have JavaScript enabled.
+ .. versionadded:: 1.6
+
+ :meth:`InlineModelAdmin.get_extra` also allows you to customize the number
+ of extra forms.
+
.. _ref-contrib-admin-inline-max-num:
.. attribute:: InlineModelAdmin.max_num
@@ -1762,6 +1767,26 @@ The ``InlineModelAdmin`` class adds:
Returns a ``BaseInlineFormSet`` class for use in admin add/change views.
See the example for :class:`ModelAdmin.get_formsets`.
+.. method:: InlineModelAdmin.get_extra(self, request, obj=None, **kwargs)
+
+ .. versionadded:: 1.6
+
+ Returns the number of extra inline forms to use. By default, returns the
+ :attr:`InlineModelAdmin.extra` attribute.
+
+ Override this method to programmatically determine the number of extra
+ inline forms. For example, this may be based on the model instance
+ (passed as the keyword argument ``obj``)::
+
+ class BinaryTreeAdmin(admin.TabularInline):
+ model = BinaryTree
+
+ def get_extra(self, request, obj=None, **kwargs):
+ extra = 2
+ if obj:
+ return extra - obj.binarytree_set.count()
+ return extra
+
Working with a model with two or more foreign keys to the same parent model
---------------------------------------------------------------------------
View
4 docs/releases/1.6.txt
@@ -292,6 +292,10 @@ Minor features
:meth:`~django.db.models.query.QuerySet.select_related` can be cleared using
``select_related(None)``.
+* The :meth:`~django.contrib.admin.InlineModelAdmin.get_extra` method on
+ :class:`~django.contrib.admin.InlineModelAdmin` may be overridden to
+ customize the number of extra inline forms.
+
Backwards incompatible changes in 1.6
=====================================
View
12 tests/admin_inlines/admin.py
@@ -129,6 +129,17 @@ class ChildModel1Inline(admin.TabularInline):
class ChildModel2Inline(admin.StackedInline):
model = ChildModel2
+# admin for #19425
+class BinaryTreeAdmin(admin.TabularInline):
+ model = BinaryTree
+
+ def get_extra(self, request, obj=None, **kwargs):
+ extra = 2
+ if obj:
+ return extra - obj.binarytree_set.count()
+
+ return extra
+
# admin for #19524
class SightingInline(admin.TabularInline):
model = Sighting
@@ -150,4 +161,5 @@ class SightingInline(admin.TabularInline):
site.register(CapoFamiglia, inlines=[ConsigliereInline, SottoCapoInline, ReadOnlyInlineInline])
site.register(ProfileCollection, inlines=[ProfileInline])
site.register(ParentModelWithCustomPk, inlines=[ChildModel1Inline, ChildModel2Inline])
+site.register(BinaryTree, inlines=[BinaryTreeAdmin])
site.register(ExtraTerrestrial, inlines=[SightingInline])
View
6 tests/admin_inlines/models.py
@@ -183,6 +183,12 @@ class ChildModel2(models.Model):
def get_absolute_url(self):
return '/child_model2/'
+
+# Models for #19425
+class BinaryTree(models.Model):
+ name = models.CharField(max_length=100)
+ parent = models.ForeignKey('self', null=True, blank=True)
+
# Models for #19524
class LifeForm(models.Model):
View
14 tests/admin_inlines/tests.py
@@ -12,7 +12,7 @@
from .models import (Holder, Inner, Holder2, Inner2, Holder3, Inner3, Person,
OutfitItem, Fashionista, Teacher, Parent, Child, Author, Book, Profile,
ProfileCollection, ParentModelWithCustomPk, ChildModel1, ChildModel2,
- Sighting, Title, Novel, Chapter, FootNote)
+ Sighting, Title, Novel, Chapter, FootNote, BinaryTree)
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
@@ -193,6 +193,18 @@ def test_create_inlines_on_inherited_model(self):
self.assertEqual(response.status_code, 302)
self.assertEqual(Sighting.objects.filter(et__name='Martian').count(), 1)
+ def test_custom_get_extra_form(self):
+ bt_head = BinaryTree.objects.create(name="Tree Head")
+ bt_child = BinaryTree.objects.create(name="First Child", parent=bt_head)
+
+ # The total number of forms will remain the same in either case
+ total_forms_hidden = '<input id="id_binarytree_set-TOTAL_FORMS" name="binarytree_set-TOTAL_FORMS" type="hidden" value="2" />'
+ response = self.client.get('/admin/admin_inlines/binarytree/add/')
+ self.assertContains(response, total_forms_hidden)
+
+ response = self.client.get("/admin/admin_inlines/binarytree/%d/" % bt_head.id)
+ self.assertContains(response, total_forms_hidden)
+
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class TestInlineMedia(TestCase):

0 comments on commit 36aecb1

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