summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHasan Ramezani <hasan.r67@gmail.com>2019-03-19 16:13:26 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2019-04-17 07:16:04 +0200
commit917fd9d03fdd21538864af4b412ac30b36d99268 (patch)
treeba9a1b26cac9b7a8c5f8258e00ac4f1832bef26a
parent7d49ad76562e8c0597a0eb66046ab423b12888d8 (diff)
downloaddjango-917fd9d03fdd21538864af4b412ac30b36d99268.tar.gz
Fixed #27755 -- Added ModelAdmin.get_inlines() hook.
-rw-r--r--django/contrib/admin/options.py6
-rw-r--r--docs/ref/contrib/admin/index.txt10
-rw-r--r--docs/releases/3.0.txt4
-rw-r--r--tests/generic_inline_admin/tests.py26
4 files changed, 45 insertions, 1 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 5e7b23f9a0..d64a2e9a28 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -327,6 +327,10 @@ class BaseModelAdmin(metaclass=forms.MediaDefiningClass):
return self.fieldsets
return [(None, {'fields': self.get_fields(request, obj)})]
+ def get_inlines(self, request, obj):
+ """Hook for specifying custom inlines."""
+ return self.inlines
+
def get_ordering(self, request):
"""
Hook for specifying field ordering.
@@ -582,7 +586,7 @@ class ModelAdmin(BaseModelAdmin):
def get_inline_instances(self, request, obj=None):
inline_instances = []
- for inline_class in self.inlines:
+ for inline_class in self.get_inlines(request, obj):
inline = inline_class(self.model, self.admin_site)
if request:
if not (inline.has_view_or_change_permission(request, obj) or
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index 93679c46fd..e6bb91cf5c 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -1627,6 +1627,16 @@ templates used by the :class:`ModelAdmin` views:
instances of the classes defined in :attr:`inlines` or you might encounter
a "Bad Request" error when adding related objects.
+.. method:: ModelAdmin.get_inlines(request, obj)
+
+ .. versionadded:: 3.0
+
+ The ``get_inlines`` method is given the ``HttpRequest`` and the
+ ``obj`` being edited (or ``None`` on an add form) and is expected to return
+ an iterable of inlines. You can override this method to dynamically add
+ inlines based on the request or model instance instead of specifying them
+ in :attr:`ModelAdmin.inlines`.
+
.. method:: ModelAdmin.get_urls()
The ``get_urls`` method on a ``ModelAdmin`` returns the URLs to be used for
diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt
index d7ad7a8cf7..44656b11cd 100644
--- a/docs/releases/3.0.txt
+++ b/docs/releases/3.0.txt
@@ -47,6 +47,10 @@ Minor features
* Added support for the ``admin_order_field`` attribute on properties in
:attr:`.ModelAdmin.list_display`.
+* The new :meth:`ModelAdmin.get_inlines()
+ <django.contrib.admin.ModelAdmin.get_inlines>` method allows specifying the
+ inlines based on the request or model instance.
+
:mod:`django.contrib.admindocs`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/generic_inline_admin/tests.py b/tests/generic_inline_admin/tests.py
index 36f1822805..b9f678a13a 100644
--- a/tests/generic_inline_admin/tests.py
+++ b/tests/generic_inline_admin/tests.py
@@ -429,3 +429,29 @@ class GenericInlineModelAdminTest(SimpleTestCase):
inlines = ma.get_inline_instances(request)
for (formset, inline), other_inline in zip(ma.get_formsets_with_inlines(request), inlines):
self.assertIsInstance(formset, other_inline.get_formset(request).__class__)
+
+ def test_get_inline_instances_override_get_inlines(self):
+ class MediaInline(GenericTabularInline):
+ model = Media
+
+ class AlternateInline(GenericTabularInline):
+ model = Media
+
+ class EpisodeAdmin(admin.ModelAdmin):
+ inlines = (AlternateInline, MediaInline)
+
+ def get_inlines(self, request, obj):
+ if hasattr(request, 'name'):
+ if request.name == 'alternate':
+ return self.inlines[:1]
+ elif request.name == 'media':
+ return self.inlines[1:2]
+ return []
+
+ ma = EpisodeAdmin(Episode, self.site)
+ self.assertEqual(ma.get_inlines(request, None), [])
+ self.assertEqual(ma.get_inline_instances(request), [])
+ for name, inline_class in (('alternate', AlternateInline), ('media', MediaInline)):
+ request.name = name
+ self.assertEqual(ma.get_inlines(request, None), (inline_class,)),
+ self.assertEqual(type(ma.get_inline_instances(request)[0]), inline_class)