diff --git a/django/contrib/admin/templates/admin/change_form.html b/django/contrib/admin/templates/admin/change_form.html
index bd71d97f3c..d68f71ebd3 100644
--- a/django/contrib/admin/templates/admin/change_form.html
+++ b/django/contrib/admin/templates/admin/change_form.html
@@ -10,7 +10,7 @@
{% block coltype %}colM{% endblock %}
-{% block bodyclass %}app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
+{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
diff --git a/django/contrib/admin/templates/admin/change_list.html b/django/contrib/admin/templates/admin/change_list.html
index 407b0e0774..586942d174 100644
--- a/django/contrib/admin/templates/admin/change_list.html
+++ b/django/contrib/admin/templates/admin/change_list.html
@@ -32,7 +32,7 @@
{% endif %}{% endif %}
{% endblock %}
-{% block bodyclass %}app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %}
+{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
diff --git a/django/contrib/admin/templates/admin/delete_confirmation.html b/django/contrib/admin/templates/admin/delete_confirmation.html
index 8e8962ff08..9d5172ad6a 100644
--- a/django/contrib/admin/templates/admin/delete_confirmation.html
+++ b/django/contrib/admin/templates/admin/delete_confirmation.html
@@ -1,7 +1,7 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_urls %}
-{% block bodyclass %}app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %}
+{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %}
{% block breadcrumbs %}
diff --git a/django/contrib/admin/templates/admin/delete_selected_confirmation.html b/django/contrib/admin/templates/admin/delete_selected_confirmation.html
index 3013c6a235..79ea977d26 100644
--- a/django/contrib/admin/templates/admin/delete_selected_confirmation.html
+++ b/django/contrib/admin/templates/admin/delete_selected_confirmation.html
@@ -1,7 +1,7 @@
{% extends "admin/base_site.html" %}
{% load i18n l10n admin_urls %}
-{% block bodyclass %}app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation delete-selected-confirmation{% endblock %}
+{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation delete-selected-confirmation{% endblock %}
{% block breadcrumbs %}
diff --git a/django/contrib/admin/templates/admin/index.html b/django/contrib/admin/templates/admin/index.html
index 7b4c1e1221..fcf269e220 100644
--- a/django/contrib/admin/templates/admin/index.html
+++ b/django/contrib/admin/templates/admin/index.html
@@ -5,7 +5,7 @@
{% block coltype %}colMS{% endblock %}
-{% block bodyclass %}dashboard{% endblock %}
+{% block bodyclass %}{{ block.super }} dashboard{% endblock %}
{% block breadcrumbs %}{% endblock %}
diff --git a/django/contrib/admin/templates/admin/login.html b/django/contrib/admin/templates/admin/login.html
index 1c8ae35c35..bf1b3f9382 100644
--- a/django/contrib/admin/templates/admin/login.html
+++ b/django/contrib/admin/templates/admin/login.html
@@ -3,7 +3,7 @@
{% block extrastyle %}{{ block.super }}{% endblock %}
-{% block bodyclass %}login{% endblock %}
+{% block bodyclass %}{{ block.super }} login{% endblock %}
{% block nav-global %}{% endblock %}
diff --git a/tests/admin_views/templates/admin/base_site.html b/tests/admin_views/templates/admin/base_site.html
new file mode 100644
index 0000000000..0502239997
--- /dev/null
+++ b/tests/admin_views/templates/admin/base_site.html
@@ -0,0 +1,3 @@
+{% extends "admin/base.html" %}
+
+{% block bodyclass%}bodyclass_consistency_check{% endblock %}
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 1ea9b4b657..2bfc3258f5 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -58,6 +58,7 @@ from .admin import site, site2, CityAdmin
ERROR_MESSAGE = "Please enter the correct username and password \
for a staff account. Note that both fields may be case-sensitive."
+ADMIN_VIEW_TEMPLATES_DIR = settings.TEMPLATE_DIRS + (os.path.join(os.path.dirname(upath(__file__)), 'templates'),)
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',),
@@ -648,6 +649,83 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
reverse('admin:app_list', args=('admin_views2',))
+@override_settings(TEMPLATE_DIRS=ADMIN_VIEW_TEMPLATES_DIR)
+class AdminCustomTemplateTests(AdminViewBasicTestCase):
+ def test_extended_bodyclass_template_change_form(self):
+ """
+ Ensure that the admin/change_form.html template uses block.super in the
+ bodyclass block.
+ """
+ response = self.client.get('/test_admin/%s/admin_views/section/add/' % self.urlbit)
+ self.assertContains(response, 'bodyclass_consistency_check ')
+
+ def test_extended_bodyclass_template_change_password(self):
+ """
+ Ensure that the auth/user/change_password.html template uses block
+ super in the bodyclass block.
+ """
+ user = User.objects.get(username='super')
+ response = self.client.get('/test_admin/%s/auth/user/%s/password/' % (self.urlbit, user.id))
+ self.assertContains(response, 'bodyclass_consistency_check ')
+
+ def test_extended_bodyclass_template_index(self):
+ """
+ Ensure that the admin/index.html template uses block.super in the
+ bodyclass block.
+ """
+ response = self.client.get('/test_admin/%s/' % self.urlbit)
+ self.assertContains(response, 'bodyclass_consistency_check ')
+
+ def test_extended_bodyclass_change_list(self):
+ """
+ Ensure that the admin/change_list.html' template uses block.super
+ in the bodyclass block.
+ """
+ response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit)
+ self.assertContains(response, 'bodyclass_consistency_check ')
+
+ def test_extended_bodyclass_template_login(self):
+ """
+ Ensure that the admin/login.html template uses block.super in the
+ bodyclass block.
+ """
+ self.client.logout()
+ response = self.client.get('/test_admin/%s/login/' % self.urlbit)
+ self.assertContains(response, 'bodyclass_consistency_check ')
+
+ def test_extended_bodyclass_template_delete_confirmation(self):
+ """
+ Ensure that the admin/delete_confirmation.html template uses
+ block.super in the bodyclass block.
+ """
+ group = Group.objects.create(name="foogroup")
+ response = self.client.get('/test_admin/%s/auth/group/%s/delete/' % (self.urlbit, group.id))
+ self.assertContains(response, 'bodyclass_consistency_check ')
+
+ def test_extended_bodyclass_template_delete_selected_confirmation(self):
+ """
+ Ensure that the admin/delete_selected_confirmation.html template uses
+ block.super in bodyclass block.
+ """
+ group = Group.objects.create(name="foogroup")
+ post_data = {
+ 'action': 'delete_selected',
+ 'selected_accross': '0',
+ 'index': '0',
+ '_selected_action': group.id
+ }
+ response = self.client.post('/test_admin/%s/auth/group/' % (self.urlbit), post_data)
+ self.assertContains(response, 'bodyclass_consistency_check ')
+
+ def test_filter_with_custom_template(self):
+ """
+ Ensure that one can use a custom template to render an admin filter.
+ Refs #17515.
+ """
+ response = self.client.get("/test_admin/admin/admin_views/color2/")
+ self.assertTemplateUsed(response, 'custom_filter_template.html')
+
+
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class AdminViewFormUrlTest(TestCase):
urls = "admin_views.urls"
@@ -668,17 +746,6 @@ class AdminViewFormUrlTest(TestCase):
self.assertTrue('form_url' in response.context, msg='form_url not present in response.context')
self.assertEqual(response.context['form_url'], 'pony')
- def test_filter_with_custom_template(self):
- """
- Ensure that one can use a custom template to render an admin filter.
- Refs #17515.
- """
- template_dirs = settings.TEMPLATE_DIRS + (
- os.path.join(os.path.dirname(upath(__file__)), 'templates'),)
- with self.settings(TEMPLATE_DIRS=template_dirs):
- response = self.client.get("/test_admin/admin/admin_views/color2/")
- self.assertTemplateUsed(response, 'custom_filter_template.html')
-
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class AdminJavaScriptTest(TestCase):
@@ -3874,7 +3941,7 @@ class CSSTest(TestCase):
response = self.client.get('/test_admin/admin/admin_views/section/add/')
self.assertEqual(response.status_code, 200)
self.assertContains(response,
- '