mirror of https://github.com/django/django.git
Fixed #494 -- Added ability to specify classes on admin inline fieldsets.
This includes the ability to collapse inlines by specifying a class named 'collapse'.
This commit is contained in:
parent
63a6a653d4
commit
5399ccc0f4
|
@ -235,6 +235,7 @@ class InlineAdminFormSet(object):
|
||||||
if prepopulated_fields is None:
|
if prepopulated_fields is None:
|
||||||
prepopulated_fields = {}
|
prepopulated_fields = {}
|
||||||
self.prepopulated_fields = prepopulated_fields
|
self.prepopulated_fields = prepopulated_fields
|
||||||
|
self.classes = ' '.join(inline.classes) if inline.classes else ''
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
|
for form, original in zip(self.formset.initial_forms, self.formset.get_queryset()):
|
||||||
|
|
|
@ -1800,6 +1800,7 @@ class InlineModelAdmin(BaseModelAdmin):
|
||||||
can_delete = True
|
can_delete = True
|
||||||
show_change_link = False
|
show_change_link = False
|
||||||
checks_class = InlineModelAdminChecks
|
checks_class = InlineModelAdminChecks
|
||||||
|
classes = None
|
||||||
|
|
||||||
def __init__(self, parent_model, admin_site):
|
def __init__(self, parent_model, admin_site):
|
||||||
self.admin_site = admin_site
|
self.admin_site = admin_site
|
||||||
|
@ -1819,6 +1820,8 @@ class InlineModelAdmin(BaseModelAdmin):
|
||||||
'inlines%s.js' % extra]
|
'inlines%s.js' % extra]
|
||||||
if self.filter_vertical or self.filter_horizontal:
|
if self.filter_vertical or self.filter_horizontal:
|
||||||
js.extend(['SelectBox.js', 'SelectFilter2.js'])
|
js.extend(['SelectBox.js', 'SelectFilter2.js'])
|
||||||
|
if self.classes and 'collapse' in self.classes:
|
||||||
|
js.append('collapse%s.js' % extra)
|
||||||
return forms.Media(js=['admin/js/%s' % url for url in js])
|
return forms.Media(js=['admin/js/%s' % url for url in js])
|
||||||
|
|
||||||
def get_extra(self, request, obj=None, **kwargs):
|
def get_extra(self, request, obj=None, **kwargs):
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
id="{{ inline_admin_formset.formset.prefix }}-group"
|
id="{{ inline_admin_formset.formset.prefix }}-group"
|
||||||
data-inline-type="stacked"
|
data-inline-type="stacked"
|
||||||
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
||||||
|
<fieldset class="module {{ inline_admin_formset.classes }}">
|
||||||
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
||||||
{{ inline_admin_formset.formset.management_form }}
|
{{ inline_admin_formset.formset.management_form }}
|
||||||
{{ inline_admin_formset.formset.non_form_errors }}
|
{{ inline_admin_formset.formset.non_form_errors }}
|
||||||
|
@ -20,4 +21,5 @@
|
||||||
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
|
||||||
{{ inline_admin_form.fk_field.field }}
|
{{ inline_admin_form.fk_field.field }}
|
||||||
</div>{% endfor %}
|
</div>{% endfor %}
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
|
||||||
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
|
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
|
||||||
{{ inline_admin_formset.formset.management_form }}
|
{{ inline_admin_formset.formset.management_form }}
|
||||||
<fieldset class="module">
|
<fieldset class="module {{ inline_admin_formset.classes }}">
|
||||||
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
|
||||||
{{ inline_admin_formset.formset.non_form_errors }}
|
{{ inline_admin_formset.formset.non_form_errors }}
|
||||||
<table>
|
<table>
|
||||||
|
|
|
@ -2058,6 +2058,16 @@ The ``InlineModelAdmin`` class adds:
|
||||||
parent model fails to validate, it may be left in an inconsistent state as
|
parent model fails to validate, it may be left in an inconsistent state as
|
||||||
described in the warning in :ref:`validation-on-modelform`.
|
described in the warning in :ref:`validation-on-modelform`.
|
||||||
|
|
||||||
|
.. attribute:: InlineModelAdmin.classes
|
||||||
|
|
||||||
|
.. versionadded:: 1.10
|
||||||
|
|
||||||
|
A list or tuple containing extra CSS classes to apply to the fieldset that
|
||||||
|
is rendered for the inlines. Defaults to ``None``. As with classes
|
||||||
|
configured in :attr:`~ModelAdmin.fieldsets`, inlines with a ``collapse``
|
||||||
|
class will be initially collapsed and their header will have a small "show"
|
||||||
|
link.
|
||||||
|
|
||||||
.. attribute:: InlineModelAdmin.extra
|
.. attribute:: InlineModelAdmin.extra
|
||||||
|
|
||||||
This controls the number of extra forms the formset will display in
|
This controls the number of extra forms the formset will display in
|
||||||
|
|
|
@ -42,6 +42,11 @@ Minor features
|
||||||
* All inline JavaScript is removed so you can enable the
|
* All inline JavaScript is removed so you can enable the
|
||||||
``Content-Security-Policy`` HTTP header if you wish.
|
``Content-Security-Policy`` HTTP header if you wish.
|
||||||
|
|
||||||
|
* The new :attr:`InlineModelAdmin.classes
|
||||||
|
<django.contrib.admin.InlineModelAdmin.classes>` attribute allows specifying
|
||||||
|
classes on inline fieldsets. Inlines with a ``collapse`` class will be
|
||||||
|
initially collapsed and their header will have a small "show" link.
|
||||||
|
|
||||||
:mod:`django.contrib.admindocs`
|
:mod:`django.contrib.admindocs`
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,12 @@ class BookInline(admin.TabularInline):
|
||||||
|
|
||||||
class NonAutoPKBookTabularInline(admin.TabularInline):
|
class NonAutoPKBookTabularInline(admin.TabularInline):
|
||||||
model = NonAutoPKBook
|
model = NonAutoPKBook
|
||||||
|
classes = ('collapse',)
|
||||||
|
|
||||||
|
|
||||||
class NonAutoPKBookStackedInline(admin.StackedInline):
|
class NonAutoPKBookStackedInline(admin.StackedInline):
|
||||||
model = NonAutoPKBook
|
model = NonAutoPKBook
|
||||||
|
classes = ('collapse',)
|
||||||
|
|
||||||
|
|
||||||
class EditablePKBookTabularInline(admin.TabularInline):
|
class EditablePKBookTabularInline(admin.TabularInline):
|
||||||
|
|
|
@ -874,6 +874,25 @@ class SeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
|
||||||
self.assertEqual(len(self.selenium.find_elements_by_css_selector(
|
self.assertEqual(len(self.selenium.find_elements_by_css_selector(
|
||||||
"%s.row2" % row_selector)), 1, msg="Expect one row2 styled row")
|
"%s.row2" % row_selector)), 1, msg="Expect one row2 styled row")
|
||||||
|
|
||||||
|
def test_collapsed_inlines(self):
|
||||||
|
# Collapsed inlines have SHOW/HIDE links.
|
||||||
|
self.admin_login(username='super', password='secret')
|
||||||
|
self.selenium.get(self.live_server_url + reverse('admin:admin_inlines_author_add'))
|
||||||
|
# One field is in a stacked inline, other in a tabular one.
|
||||||
|
test_fields = ['id_nonautopkbook_set-0-title', 'id_nonautopkbook_set-2-0-title']
|
||||||
|
show_links = self.selenium.find_elements_by_link_text('SHOW')
|
||||||
|
self.assertEqual(len(show_links), 2)
|
||||||
|
for show_index, field_name in enumerate(test_fields, 0):
|
||||||
|
self.assertFalse(self.selenium.find_element_by_id(field_name).is_displayed())
|
||||||
|
show_links[show_index].click()
|
||||||
|
self.assertTrue(self.selenium.find_element_by_id(field_name).is_displayed())
|
||||||
|
hide_links = self.selenium.find_elements_by_link_text('HIDE')
|
||||||
|
self.assertEqual(len(hide_links), 2)
|
||||||
|
for hide_index, field_name in enumerate(test_fields, 0):
|
||||||
|
self.assertTrue(self.selenium.find_element_by_id(field_name).is_displayed())
|
||||||
|
hide_links[hide_index].click()
|
||||||
|
self.assertFalse(self.selenium.find_element_by_id(field_name).is_displayed())
|
||||||
|
|
||||||
|
|
||||||
class SeleniumChromeTests(SeleniumFirefoxTests):
|
class SeleniumChromeTests(SeleniumFirefoxTests):
|
||||||
webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
|
webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
|
||||||
|
|
Loading…
Reference in New Issue