Ticket #25: select_filter_for_Django_1_4.diff
File select_filter_for_Django_1_4.diff, 8.4 KB (added by , 12 years ago) |
---|
-
AUTHORS
diff --git a/AUTHORS b/AUTHORS index 8224cda..443ba92 100644
a b answer newbie questions, and generally made Django that much better: 90 90 Mark Biggers <biggers@utsl.com> 91 91 Paul Bissex <http://e-scribe.com/> 92 92 Simon Blanchard 93 Sean Bleier <sebleier@gmail.com> 93 94 David Blewett <david@dawninglight.net> 94 95 Matt Boersma <matt@sprout.org> 95 96 boobsd@gmail.com … … answer newbie questions, and generally made Django that much better: 227 228 Scot Hacker <shacker@birdhouse.org> 228 229 dAniel hAhler 229 230 hambaloney 231 Chuck Harmston <chuck@chuckharmston.com> 230 232 Brian Harring <ferringb@gmail.com> 231 233 Brant Harris 232 234 Ronny Haryanto <http://ronny.haryan.to/> -
django/contrib/admin/options.py
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 3a0ad74..3deb0f1 100644
a b class BaseModelAdmin(object): 163 163 'class': get_ul_class(self.radio_fields[db_field.name]), 164 164 }) 165 165 kwargs['empty_label'] = db_field.blank and _('None') or None 166 elif db_field.name in self.filter_vertical: 167 kwargs['widget'] = widgets.FilteredSelectSingle(db_field.verbose_name) 166 168 167 169 return db_field.formfield(**kwargs) 168 170 … … class InlineModelAdmin(BaseModelAdmin): 1375 1377 if self.prepopulated_fields: 1376 1378 js.extend(['urlify.js', 'prepopulate.min.js']) 1377 1379 if self.filter_vertical or self.filter_horizontal: 1378 js.extend(['SelectBox.js', 'SelectFilter2.js' ])1380 js.extend(['SelectBox.js', 'SelectFilter2.js', 'fkfilter.js']) 1379 1381 return forms.Media(js=[static('admin/js/%s' % url) for url in js]) 1380 1382 1381 1383 def get_formset(self, request, obj=None, **kwargs): -
django/contrib/admin/static/admin/css/widgets.css
diff --git a/django/contrib/admin/static/admin/css/widgets.css b/django/contrib/admin/static/admin/css/widgets.css index 2989f2f..451f3e9 100644
a b 5 5 float: left; 6 6 } 7 7 8 .selector-single{ 9 width: 282px !important; 10 } 11 8 12 .selector select { 9 13 width: 270px; 10 14 height: 17.2em; -
django/contrib/admin/validation.py
diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py index 733f89d..500bfcb 100644
a b def validate_base(cls, model): 323 323 check_isseq(cls, 'filter_vertical', cls.filter_vertical) 324 324 for idx, field in enumerate(cls.filter_vertical): 325 325 f = get_field(cls, model, opts, 'filter_vertical', field) 326 if not isinstance(f, models.ManyToManyField):326 if not isinstance(f, (models.ManyToManyField, models.ForeignKey)): 327 327 raise ImproperlyConfigured("'%s.filter_vertical[%d]' must be " 328 "a ManyToManyField ." % (cls.__name__, idx))328 "a ManyToManyField or ForeignKey." % (cls.__name__, idx)) 329 329 330 330 # filter_horizontal 331 331 if hasattr(cls, 'filter_horizontal'): -
django/contrib/admin/widgets.py
diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py index 0d1f2a9..0bd1b0c 100644
a b from django.utils.safestring import mark_safe 15 15 from django.utils.encoding import force_unicode 16 16 17 17 18 class FilteredSelectSingle(forms.Select): 19 """ 20 A Select with a JavaScript filter interface. 21 """ 22 #class Media: 23 # js = (settings.ADMIN_MEDIA_PREFIX + "js/fkfilter.js",) 24 # TODO: mimic newer 'def media' below... 25 @property 26 def media(self): 27 js = ["core.js", "fkfilter.js"] 28 return forms.Media(js=[static("admin/js/%s" % path) for path in js]) 29 30 def __init__(self, verbose_name, attrs=None, choices=()): 31 self.verbose_name = verbose_name 32 super(FilteredSelectSingle, self).__init__(attrs, choices) 33 34 def render(self, name, value, attrs={}, choices=()): 35 attrs['class'] = 'selectfilter' 36 output = [super(FilteredSelectSingle, self).render( 37 name, value, attrs, choices)] 38 output.append(( 39 '<script type="text/javascript">' 40 'django.jQuery(document).ready(function(){' 41 'django.jQuery("#id_%s").fk_filter("%s")' 42 '});' 43 '</script>' 44 ) % (name, self.verbose_name.replace('"', '\\"'),)); 45 return mark_safe(u''.join(output)) 46 47 18 48 class FilteredSelectMultiple(forms.SelectMultiple): 19 49 """ 20 50 A SelectMultiple with a JavaScript filter interface. -
docs/ref/contrib/admin/index.txt
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index 2590243..c218036 100644
a b subclass:: 303 303 304 304 Same as :attr:`~ModelAdmin.filter_horizontal`, but uses a vertical display 305 305 of the filter interface with the box of unselected options appearing above 306 the box of selected options. 306 the box of selected options You can also add a 307 :class:`~django.db.models.ForeignKey` to this list and a text bo will 308 allow you to narrow your search for a particular object through a 309 potentially large list of options. 307 310 308 311 .. attribute:: ModelAdmin.form 309 312 -
tests/regressiontests/admin_widgets/tests.py
diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py index 08a1a59..186a602 100644
a b class AdminForeignKeyRawIdWidget(DjangoTestCase): 190 190 self.assertEqual(lookup1, lookup2) 191 191 192 192 193 class FilteredSelectSingleWidgetTest(DjangoTestCase): 194 def test_render(self): 195 w = widgets.FilteredSelectSingle('test') 196 self.assertEqual( 197 conditional_escape(w.render('test', 'test')), 198 '<select name="test" class="selectfilter">\n</select><script type="text/javascript">django.jQuery(document).ready(function(){django.jQuery("#id_test").fk_filter("test")});</script>' 199 ) 200 193 201 class FilteredSelectMultipleWidgetTest(DjangoTestCase): 194 202 def test_render(self): 195 203 w = widgets.FilteredSelectMultiple('test', False) -
tests/regressiontests/modeladmin/tests.py
diff --git a/tests/regressiontests/modeladmin/tests.py b/tests/regressiontests/modeladmin/tests.py index 9b60945..99092be 100644
a b from django.contrib.admin.options import (ModelAdmin, TabularInline, 8 8 HORIZONTAL, VERTICAL) 9 9 from django.contrib.admin.sites import AdminSite 10 10 from django.contrib.admin.validation import validate 11 from django.contrib.admin.widgets import AdminDateWidget, AdminRadioSelect 11 from django.contrib.admin.widgets import AdminDateWidget, AdminRadioSelect, \ 12 FilteredSelectSingle 12 13 from django.contrib.admin import (SimpleListFilter, 13 14 BooleanFieldListFilter) 14 15 from django.core.exceptions import ImproperlyConfigured … … class ModelAdminTests(TestCase): 493 494 list(ma.get_formsets(request))[0]().forms[0].fields.keys(), 494 495 ['extra', 'transport', 'id', 'DELETE', 'main_band']) 495 496 497 def test_filter_vertical_foreignkey(self): 498 class ConcertModelAdmin(ModelAdmin): 499 filter_vertical = ('main_band',) 500 501 cma = ConcertModelAdmin(Concert, self.site) 502 cmafa = cma.get_form(request) 503 504 self.assertEqual(type(cmafa.base_fields['main_band'].widget.widget), 505 FilteredSelectSingle) 506 self.assertEqual(type(cmafa.base_fields['opening_band'].widget.widget), 507 Select) 508 509 self.assertEqual( 510 list(cmafa.base_fields['main_band'].widget.choices), 511 [(u'', u'---------'), (self.band.id, u'The Doors')]) 512 513 self.assertEqual( 514 type(cmafa.base_fields['opening_band'].widget.widget), Select) 515 self.assertEqual( 516 list(cmafa.base_fields['opening_band'].widget.choices), 517 [(u'', u'---------'), (self.band.id, u'The Doors')]) 518 519 self.assertEqual(type(cmafa.base_fields['day'].widget), Select) 520 self.assertEqual(list(cmafa.base_fields['day'].widget.choices), 521 [('', '---------'), (1, 'Fri'), (2, 'Sat')]) 522 523 self.assertEqual(type(cmafa.base_fields['transport'].widget), 524 Select) 525 self.assertEqual( 526 list(cmafa.base_fields['transport'].widget.choices), 527 [('', '---------'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')]) 528 496 529 497 530 class ValidationTests(unittest.TestCase): 498 531 def test_validation_only_runs_in_debug(self):