Fixed #17515 -- Added ability to override the template of custom admin FilterSpec classes. Thanks, saxix and Julien Phalip.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17483 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jannis Leidel 2012-02-09 18:59:05 +00:00
parent 875a5ea8d4
commit 4dbeb4bca4
7 changed files with 55 additions and 6 deletions

View File

@ -17,6 +17,7 @@ from django.contrib.admin.util import (get_model_from_relation,
class ListFilter(object): class ListFilter(object):
title = None # Human-readable title to appear in the right sidebar. title = None # Human-readable title to appear in the right sidebar.
template = 'admin/filter.html'
def __init__(self, request, params, model, model_admin): def __init__(self, request, params, model, model_admin):
# This dictionary will eventually contain the request's query string # This dictionary will eventually contain the request's query string

View File

@ -13,7 +13,8 @@ from django.utils.text import capfirst
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils.encoding import smart_unicode, force_unicode from django.utils.encoding import smart_unicode, force_unicode
from django.template import Library from django.template import Library
from django.template.loader import get_template
from django.template.context import Context
register = Library() register = Library()
@ -360,9 +361,14 @@ def search_form(cl):
'search_var': SEARCH_VAR 'search_var': SEARCH_VAR
} }
@register.inclusion_tag('admin/filter.html') @register.simple_tag
def admin_list_filter(cl, spec): def admin_list_filter(cl, spec):
return {'title': spec.title, 'choices' : list(spec.choices(cl))} tpl = get_template(spec.template)
return tpl.render(Context({
'title': spec.title,
'choices' : list(spec.choices(cl)),
'spec': spec,
}))
@register.inclusion_tag('admin/actions.html', takes_context=True) @register.inclusion_tag('admin/actions.html', takes_context=True)
def admin_actions(context): def admin_actions(context):

View File

@ -697,8 +697,18 @@ subclass::
.. note:: .. note::
The ``FieldListFilter`` API is currently considered internal The ``FieldListFilter`` API is currently considered internal and prone
and prone to refactoring. to refactoring.
.. versionadded:: 1.4
It is possible to specify a custom template for rendering a list filter::
class FilterWithCustomTemplate(SimpleListFilter):
template = "custom_template.html"
See the default template provided by django (``admin/filter.html``) for
a concrete example.
.. attribute:: ModelAdmin.list_max_show_all .. attribute:: ModelAdmin.list_max_show_all

View File

@ -13,6 +13,7 @@ from django.conf.urls import patterns, url
from django.db import models from django.db import models
from django.forms.models import BaseModelFormSet from django.forms.models import BaseModelFormSet
from django.http import HttpResponse from django.http import HttpResponse
from django.contrib.admin import BooleanFieldListFilter
from .models import (Article, Chapter, Account, Media, Child, Parent, Picture, from .models import (Article, Chapter, Account, Media, Child, Parent, Picture,
Widget, DooHickey, Grommet, Whatsit, FancyDoodad, Category, Link, Widget, DooHickey, Grommet, Whatsit, FancyDoodad, Category, Link,
@ -25,7 +26,7 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture,
CoverLetter, Story, OtherStory, Book, Promo, ChapterXtra1, Pizza, Topping, CoverLetter, Story, OtherStory, Book, Promo, ChapterXtra1, Pizza, Topping,
Album, Question, Answer, ComplexSortedPerson, PrePopulatedPostLargeSlug, Album, Question, Answer, ComplexSortedPerson, PrePopulatedPostLargeSlug,
AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
AdminOrderedCallable, Report) AdminOrderedCallable, Report, Color2)
def callable_year(dt_value): def callable_year(dt_value):
@ -525,6 +526,12 @@ class ReportAdmin(admin.ModelAdmin):
) )
class CustomTemplateBooleanFieldListFilter(BooleanFieldListFilter):
template = 'custom_filter_template.html'
class CustomTemplateFilterColorAdmin(admin.ModelAdmin):
list_filter = (('warm', CustomTemplateBooleanFieldListFilter),)
site = admin.AdminSite(name="admin") site = admin.AdminSite(name="admin")
site.register(Article, ArticleAdmin) site.register(Article, ArticleAdmin)
site.register(CustomArticle, CustomArticleAdmin) site.register(CustomArticle, CustomArticleAdmin)
@ -594,6 +601,7 @@ site.register(AdminOrderedField, AdminOrderedFieldAdmin)
site.register(AdminOrderedModelMethod, AdminOrderedModelMethodAdmin) site.register(AdminOrderedModelMethod, AdminOrderedModelMethodAdmin)
site.register(AdminOrderedAdminMethod, AdminOrderedAdminMethodAdmin) site.register(AdminOrderedAdminMethod, AdminOrderedAdminMethodAdmin)
site.register(AdminOrderedCallable, AdminOrderedCallableAdmin) site.register(AdminOrderedCallable, AdminOrderedCallableAdmin)
site.register(Color2, CustomTemplateFilterColorAdmin)
# Register core models we need in our tests # Register core models we need in our tests
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group

View File

@ -105,6 +105,10 @@ class Color(models.Model):
def __unicode__(self): def __unicode__(self):
return self.value return self.value
# we replicate Color to register with another ModelAdmin
class Color2(Color):
class Meta:
proxy = True
class Thing(models.Model): class Thing(models.Model):
title = models.CharField(max_length=20) title = models.CharField(max_length=20)

View File

@ -0,0 +1,7 @@
<h3>By {{ filter_title }} (custom)</h3>
<ul>
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
<a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
{% endfor %}
</ul>

View File

@ -1,6 +1,7 @@
# coding: utf-8 # coding: utf-8
from __future__ import with_statement, absolute_import from __future__ import with_statement, absolute_import
import os
import re import re
import datetime import datetime
import urlparse import urlparse
@ -593,6 +594,18 @@ class AdminViewFormUrlTest(TestCase):
self.assertTrue('form_url' in response.context, msg='form_url not present in response.context') self.assertTrue('form_url' in response.context, msg='form_url not present in response.context')
self.assertEqual(response.context['form_url'], 'pony') 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(__file__), 'templates'),)
with self.settings(TEMPLATE_DIRS=template_dirs):
response = self.client.get("/test_admin/admin/admin_views/color2/")
self.assertTrue('custom_filter_template.html' in [t.name for t in response.templates])
class AdminJavaScriptTest(AdminViewBasicTest): class AdminJavaScriptTest(AdminViewBasicTest):
urls = "regressiontests.admin_views.urls" urls = "regressiontests.admin_views.urls"