Ticket #12566: 0001-contrib.admin-allow-overriding-of-actions.html-templ.patch

File 0001-contrib.admin-allow-overriding-of-actions.html-templ.patch, 11.0 KB (added by Tay Ray Chuan, 14 years ago)
  • django/contrib/admin/options.py

    From 2888dd42ebafd09fc856dfbcc084bc909466936e Mon Sep 17 00:00:00 2001
    From: Tay Ray Chuan <rctay89@gmail.com>
    Date: Sat, 13 Mar 2010 15:15:42 +0800
    Subject: [PATCH] contrib.admin: allow overriding of actions.html template at app level
    
     - make changelist_view() set the context variable actions_template,
       checking the usual template path
    
     - make {% admin_actions %} get and render the actions template manually
       using the path set in the context variable actions_template
    
     - update documentation to say that actions.html can be overriden at the
       app level via the ModelAdmin attribute, actions_template
    
     - add regression tests in tests/regressiontests/admin_actions
    ---
     django/contrib/admin/options.py                    |   21 ++++++++++
     django/contrib/admin/templatetags/admin_list.py    |   27 +++++++++----
     docs/ref/contrib/admin/index.txt                   |   11 +++++
     .../admin_actions/fixtures/admin-views-users.xml   |   17 ++++++++
     tests/regressiontests/admin_actions/models.py      |   19 +++++++++
     tests/regressiontests/admin_actions/tests.py       |   40 ++++++++++++++++++++
     tests/templates/admin/admin_actions/actions.html   |    3 +
     .../templates/admin/admin_actions/cat/actions.html |    3 +
     8 files changed, 132 insertions(+), 9 deletions(-)
     create mode 100644 tests/regressiontests/admin_actions/__init__.py
     create mode 100644 tests/regressiontests/admin_actions/fixtures/admin-views-users.xml
     create mode 100644 tests/regressiontests/admin_actions/models.py
     create mode 100644 tests/regressiontests/admin_actions/tests.py
     create mode 100644 tests/templates/admin/admin_actions/actions.html
     create mode 100644 tests/templates/admin/admin_actions/cat/actions.html
    
    diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
    index 1f8ff6d..6a17b46 100644
    a b from django.db import models, transaction  
    1313from django.db.models.fields import BLANK_CHOICE_DASH
    1414from django.http import Http404, HttpResponse, HttpResponseRedirect
    1515from django.shortcuts import get_object_or_404, render_to_response
     16from django.template.loader import find_template
    1617from django.utils.decorators import method_decorator
    1718from django.utils.datastructures import SortedDict
    1819from django.utils.functional import update_wrapper
    class ModelAdmin(BaseModelAdmin):  
    210211    # Actions
    211212    actions = []
    212213    action_form = helpers.ActionForm
     214    actions_template = None
    213215    actions_on_top = True
    214216    actions_on_bottom = False
    215217    actions_selection_counter = True
    class ModelAdmin(BaseModelAdmin):  
    10601062        if actions:
    10611063            action_form = self.action_form(auto_id=None)
    10621064            action_form.fields['action'].choices = self.get_action_choices(request)
     1065
     1066            if self.actions_template:
     1067                actions_template = self.actions_template
     1068            else:
     1069                # Search for the appropriate template path for inclusion by {% admin_actions %}
     1070                for t in (
     1071                    'admin/%s/%s/actions.html' % (app_label, opts.object_name.lower()),
     1072                    'admin/%s/actions.html' % app_label,
     1073                    'admin/actions.html',
     1074                ):
     1075                    try:
     1076                        find_template(t)
     1077                    except template.TemplateDoesNotExist:
     1078                        continue
     1079                    else:
     1080                        actions_template = t
     1081                        break
    10631082        else:
    10641083            action_form = None
     1084            actions_template = None
    10651085
    10661086        selection_note_all = ungettext('%(total_count)s selected',
    10671087            'All %(total_count)s selected', cl.result_count)
    class ModelAdmin(BaseModelAdmin):  
    10781098            'root_path': self.admin_site.root_path,
    10791099            'app_label': app_label,
    10801100            'action_form': action_form,
     1101            'actions_template': actions_template,
    10811102            'actions_on_top': self.actions_on_top,
    10821103            'actions_on_bottom': self.actions_on_bottom,
    10831104            'actions_selection_counter': self.actions_selection_counter,
  • django/contrib/admin/templatetags/admin_list.py

    diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py
    index 565db32..6f65044 100644
    a b from django.utils.safestring import mark_safe  
    1313from django.utils.text import capfirst
    1414from django.utils.translation import ugettext as _
    1515from django.utils.encoding import smart_unicode, force_unicode
    16 from django.template import Library
     16from django.template import Library, Node
     17from django.template.loader import get_template
    1718
    1819
    1920register = Library()
    def admin_list_filter(cl, spec):  
    287288    return {'title': spec.title(), 'choices' : list(spec.choices(cl))}
    288289admin_list_filter = register.inclusion_tag('admin/filter.html')(admin_list_filter)
    289290
    290 def admin_actions(context):
    291     """
    292     Track the number of times the action field has been rendered on the page,
    293     so we know which value to use.
    294     """
    295     context['action_index'] = context.get('action_index', -1) + 1
    296     return context
    297 admin_actions = register.inclusion_tag("admin/actions.html", takes_context=True)(admin_actions)
     291#@register.tag
     292def admin_actions(parser, token):
     293    class IncludeActionsTemplateNode(Node):
     294        def render(self, context):
     295            # Track the number of times the action field has been rendered on
     296            # the page, so we know which value to use.
     297            context['action_index'] = context.get('action_index', -1) + 1
     298
     299            try:
     300                t = get_template(context.get('actions_template', 'admin/actions.html'))
     301                return t.render(context)
     302            except:
     303                return ''
     304
     305    return IncludeActionsTemplateNode()
     306admin_actions = register.tag(admin_actions)
  • docs/ref/contrib/admin/index.txt

    diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
    index f7aefa4..f3c9e50 100644
    a b The `Overriding Admin Templates`_ section describes how to override or extend  
    718718the default admin templates.  Use the following options to override the default
    719719templates used by the :class:`ModelAdmin` views:
    720720
     721.. attribute:: ModelAdmin.actions_template
     722
     723.. versionadded:: 1.2
     724
     725Path to a custom template that will be used to display actions in the model
     726objects "change list" view.
     727
     728If you don't specify this attribute, a default template shipped with Django
     729that provides the standard appearance is used.
     730
    721731.. attribute:: ModelAdmin.add_form_template
    722732
    723733    .. versionadded:: 1.2
    app or per model. The following can:  
    13631373    * ``app_index.html``
    13641374    * ``change_form.html``
    13651375    * ``change_list.html``
     1376    * ``actions.html``
    13661377    * ``delete_confirmation.html``
    13671378    * ``object_history.html``
    13681379
  • new file tests/regressiontests/admin_actions/fixtures/admin-views-users.xml

    diff --git a/tests/regressiontests/admin_actions/__init__.py b/tests/regressiontests/admin_actions/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_actions/fixtures/admin-views-users.xml b/tests/regressiontests/admin_actions/fixtures/admin-views-users.xml
    new file mode 100644
    index 0000000..aba8f4a
    - +  
     1<?xml version="1.0" encoding="utf-8"?>
     2<django-objects version="1.0">
     3    <object pk="100" model="auth.user">
     4        <field type="CharField" name="username">super</field>
     5        <field type="CharField" name="first_name">Super</field>
     6        <field type="CharField" name="last_name">User</field>
     7        <field type="CharField" name="email">super@example.com</field>
     8        <field type="CharField" name="password">sha1$995a3$6011485ea3834267d719b4c801409b8b1ddd0158</field>
     9        <field type="BooleanField" name="is_staff">True</field>
     10        <field type="BooleanField" name="is_active">True</field>
     11        <field type="BooleanField" name="is_superuser">True</field>
     12        <field type="DateTimeField" name="last_login">2007-05-30 13:20:10</field>
     13        <field type="DateTimeField" name="date_joined">2007-05-30 13:20:10</field>
     14        <field to="auth.group" name="groups" rel="ManyToManyRel"></field>
     15        <field to="auth.permission" name="user_permissions" rel="ManyToManyRel"></field>
     16    </object>
     17</django-objects>
  • new file tests/regressiontests/admin_actions/models.py

    diff --git a/tests/regressiontests/admin_actions/models.py b/tests/regressiontests/admin_actions/models.py
    new file mode 100644
    index 0000000..47afed4
    - +  
     1from django.contrib import admin
     2from django.db import models
     3
     4class Animal(models.Model):
     5    name = models.CharField(max_length=128)
     6
     7    class Meta:
     8        abstract = True
     9
     10class Cat(Animal):
     11    """Used for model overrides."""
     12    pass
     13
     14class Dog(Animal):
     15    """Used for app overrides."""
     16    pass
     17
     18admin.site.register(Cat)
     19admin.site.register(Dog)
  • new file tests/regressiontests/admin_actions/tests.py

    diff --git a/tests/regressiontests/admin_actions/tests.py b/tests/regressiontests/admin_actions/tests.py
    new file mode 100644
    index 0000000..6731e74
    - +  
     1from django.test import TestCase
     2
     3from models import Cat, Dog
     4
     5class TestInline(TestCase):
     6    fixtures = ['admin-views-users.xml']
     7
     8    def setUp(self):
     9        self.base_url = '/test_admin/admin/admin_actions'
     10
     11        # this is needed for the actions form to show up (with the 'delete' action)
     12        Dog(name='Jacky').save()
     13        Cat(name='Felix').save()
     14
     15        self.app_element = '<p class="app-element"></p>'
     16        self.model_element = '<p class="model-element"></p>'
     17
     18        result = self.client.login(username='super', password='secret')
     19        self.failUnlessEqual(result, True)
     20
     21    def tearDown(self):
     22        self.client.logout()
     23
     24    def test_app_can_override(self):
     25        """
     26        Test that the actions.html template can be overriden by an app.
     27        """
     28        changelist_url = '%s/dog/' % self.base_url
     29        response = self.client.get(changelist_url)
     30
     31        self.assertContains(response, self.app_element)
     32
     33    def test_model_can_override(self):
     34        """
     35        Test that the actions.html template can be overriden by a model.
     36        """
     37        changelist_url = '%s/cat/' % self.base_url
     38        response = self.client.get(changelist_url)
     39
     40        self.assertContains(response, self.model_element)
  • new file tests/templates/admin/admin_actions/actions.html

    diff --git a/tests/templates/admin/admin_actions/actions.html b/tests/templates/admin/admin_actions/actions.html
    new file mode 100644
    index 0000000..9c5d2e4
    - +  
     1{% include "admin/actions.html" %}
     2
     3<p class="app-element"></p>
  • new file tests/templates/admin/admin_actions/cat/actions.html

    diff --git a/tests/templates/admin/admin_actions/cat/actions.html b/tests/templates/admin/admin_actions/cat/actions.html
    new file mode 100644
    index 0000000..3563c8a
    - +  
     1{% include "admin/actions.html" %}
     2
     3<p class="model-element"></p>
Back to Top