Fixed #27313 -- Allowed overriding admin popup response template.

This commit is contained in:
Michael Scott 2016-11-12 19:09:15 +00:00 committed by Tim Graham
parent fb1349ce8c
commit 1e629928e9
6 changed files with 80 additions and 6 deletions

View File

@ -509,6 +509,7 @@ class ModelAdmin(BaseModelAdmin):
delete_confirmation_template = None
delete_selected_confirmation_template = None
object_history_template = None
popup_response_template = None
# Actions
actions = []
@ -1073,7 +1074,11 @@ class ModelAdmin(BaseModelAdmin):
'value': six.text_type(value),
'obj': six.text_type(obj),
})
return SimpleTemplateResponse('admin/popup_response.html', {
return TemplateResponse(request, self.popup_response_template or [
'admin/%s/%s/popup_response.html' % (opts.app_label, opts.model_name),
'admin/%s/popup_response.html' % opts.app_label,
'admin/popup_response.html',
], {
'popup_response_data': popup_response_data,
})
@ -1119,8 +1124,9 @@ class ModelAdmin(BaseModelAdmin):
"""
if IS_POPUP_VAR in request.POST:
opts = obj._meta
to_field = request.POST.get(TO_FIELD_VAR)
attr = str(to_field) if to_field else obj._meta.pk.attname
attr = str(to_field) if to_field else opts.pk.attname
# Retrieve the `object_id` from the resolved pattern arguments.
value = request.resolver_match.args[0]
new_value = obj.serializable_value(attr)
@ -1130,7 +1136,11 @@ class ModelAdmin(BaseModelAdmin):
'obj': six.text_type(obj),
'new_value': six.text_type(new_value),
})
return SimpleTemplateResponse('admin/popup_response.html', {
return TemplateResponse(request, self.popup_response_template or [
'admin/%s/%s/popup_response.html' % (opts.app_label, opts.model_name),
'admin/%s/popup_response.html' % opts.app_label,
'admin/popup_response.html',
], {
'popup_response_data': popup_response_data,
})
@ -1299,7 +1309,11 @@ class ModelAdmin(BaseModelAdmin):
'action': 'delete',
'value': str(obj_id),
})
return SimpleTemplateResponse('admin/popup_response.html', {
return TemplateResponse(request, self.popup_response_template or [
'admin/%s/%s/popup_response.html' % (opts.app_label, opts.model_name),
'admin/%s/popup_response.html' % opts.app_label,
'admin/popup_response.html',
], {
'popup_response_data': popup_response_data,
})

View File

@ -1318,6 +1318,12 @@ templates used by the :class:`ModelAdmin` views:
Path to a custom template, used by :meth:`history_view`.
.. attribute:: ModelAdmin.popup_response_template
.. versionadded:: 1.11
Path to a custom template, used by :meth:`response_add`,
:meth:`response_change`, and :meth:`response_delete`.
.. _model-admin-methods:
@ -2516,6 +2522,11 @@ app or per model. The following can:
* ``change_list.html``
* ``delete_confirmation.html``
* ``object_history.html``
* ``popup_response.html``
.. versionchanged:: 1.11
The ability to override the ``popup_response.html`` template was added.
For those templates that cannot be overridden in this way, you may still
override them for your entire project. Just place the new version in your

View File

@ -72,6 +72,10 @@ Minor features
<django.contrib.admin.ModelAdmin.get_exclude>` hook allows specifying the
exclude fields based on the request or model instance.
* The ``popup_response.html`` template can now be overridden per app, per
model, or by setting the :attr:`.ModelAdmin.popup_response_template`
attribute.
:mod:`django.contrib.admindocs`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -162,6 +162,7 @@ class CustomArticleAdmin(admin.ModelAdmin):
object_history_template = 'custom_admin/object_history.html'
delete_confirmation_template = 'custom_admin/delete_confirmation.html'
delete_selected_confirmation_template = 'custom_admin/delete_selected_confirmation.html'
popup_response_template = 'custom_admin/popup_response.html'
def changelist_view(self, request):
return super(CustomArticleAdmin, self).changelist_view(

View File

@ -969,6 +969,16 @@ class AdminCustomTemplateTests(AdminViewBasicTestCase):
response = self.client.get(reverse('admin:admin_views_customarticle_history', args=(article_pk,)))
self.assertTemplateUsed(response, 'custom_admin/object_history.html')
# A custom popup response template may be specified by
# ModelAdmin.popup_response_template.
response = self.client.post(reverse('admin:admin_views_customarticle_add') + '?%s=1' % IS_POPUP_VAR, {
'content': '<p>great article</p>',
'date_0': '2008-03-18',
'date_1': '10:54:39',
IS_POPUP_VAR: '1'
})
self.assertEqual(response.template_name, 'custom_admin/popup_response.html')
def test_extended_bodyclass_template_change_form(self):
"""
The admin/change_form.html template uses block.super in the
@ -3433,7 +3443,7 @@ action)</option>
reverse('admin:admin_views_subscriber_changelist') + '?%s' % IS_POPUP_VAR)
self.assertIsNone(response.context["action_form"])
def test_popup_template_response(self):
def test_popup_template_response_on_add(self):
"""
Success on popups shall be rendered from template in order to allow
easy customization.
@ -3442,7 +3452,40 @@ action)</option>
reverse('admin:admin_views_actor_add') + '?%s=1' % IS_POPUP_VAR,
{'name': 'Troy McClure', 'age': '55', IS_POPUP_VAR: '1'})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template_name, 'admin/popup_response.html')
self.assertListEqual(response.template_name, [
'admin/admin_views/actor/popup_response.html',
'admin/admin_views/popup_response.html',
'admin/popup_response.html',
])
self.assertTemplateUsed(response, 'admin/popup_response.html')
def test_popup_template_response_on_change(self):
instance = Actor.objects.create(name='David Tennant', age=45)
response = self.client.post(
reverse('admin:admin_views_actor_change', args=(instance.pk,)) + '?%s=1' % IS_POPUP_VAR,
{'name': 'David Tennant', 'age': '46', IS_POPUP_VAR: '1'}
)
self.assertEqual(response.status_code, 200)
self.assertListEqual(response.template_name, [
'admin/admin_views/actor/popup_response.html',
'admin/admin_views/popup_response.html',
'admin/popup_response.html',
])
self.assertTemplateUsed(response, 'admin/popup_response.html')
def test_popup_template_response_on_delete(self):
instance = Actor.objects.create(name='David Tennant', age=45)
response = self.client.post(
reverse('admin:admin_views_actor_delete', args=(instance.pk,)) + '?%s=1' % IS_POPUP_VAR,
{IS_POPUP_VAR: '1'}
)
self.assertEqual(response.status_code, 200)
self.assertListEqual(response.template_name, [
'admin/admin_views/actor/popup_response.html',
'admin/admin_views/popup_response.html',
'admin/popup_response.html',
])
self.assertTemplateUsed(response, 'admin/popup_response.html')
def test_popup_template_escaping(self):
popup_response_data = json.dumps({

View File

@ -0,0 +1 @@
{% extends "admin/popup_response.html" %}