Skip to content
Browse files

added a LinkWidget as well as docs and tests

  • Loading branch information...
1 parent 2f15e95 commit 88d70726901952b08c2d0832a61958c98702ada5 @alex alex committed
Showing with 76 additions and 1 deletion.
  1. +5 −1 docs/ref/filters.txt
  2. +23 −0 filter/tests.py
  3. +48 −0 filter/widgets.py
View
6 docs/ref/filters.txt
@@ -86,7 +86,11 @@ argument.
``widget``
~~~~~~~~~~
-The django.form Widget class which will represent the ``Filter``.
+The django.form Widget class which will represent the ``Filter``. In addition
+to the widgets that are included with Django that you can use there are
+additional ones that django-filte provides which may be useful:
+ * ``filter.widgets.LinkWidget`` -- this displays the options in a mannner
+ similar to the way the Django Admin does, as a series of links.
``action``
~~~~~~~~~~
View
23 filter/tests.py
@@ -3,6 +3,7 @@
>>> from django.core.management import call_command
>>> import filter
>>> from filter import FilterSet
+>>> from filter.widgets import LinkWidget
>>> from filter.models import User, Comment, Book, STATUS_CHOICES
>>> call_command('loaddata', 'test_data', verbosity=0)
@@ -275,5 +276,27 @@
>>> f= F({'price_0': '15', 'price_1': 'lt'})
>>> f.qs
[<Book: Ender's Game>]
+>>> class F(FilterSet):
+... status = filter.ChoiceFilter(widget=LinkWidget, choices=STATUS_CHOICES)
+... class Meta:
+... model = User
+... fields = ['status']
+>>> f = F()
+>>> f.qs
+[<User: alex>, <User: aaron>, <User: jacob>]
+>>> print f.form
+<tr><th><label for="id_status">Status:</label></th><td><ul id="id_status">
+<a href="?status=0">Regular</a>
+<a href="?status=1">Admin</a>
+</ul></td></tr>
+>>> f = F({'status': '1'})
+>>> f.qs
+[<User: alex>]
+>>> print f.form
+<tr><th><label for="id_status">Status:</label></th><td><ul id="id_status">
+<a href="?status=0">Regular</a>
+<a href="?status=1">Admin</a>
+</ul></td></tr>
+
"""}
View
48 filter/widgets.py
@@ -1,4 +1,52 @@
+from itertools import chain
+from urllib import urlencode
+
from django import forms
+from django.forms.widgets import flatatt
+from django.utils.encoding import force_unicode
+from django.utils.safestring import mark_safe
+
+class LinkWidget(forms.Widget):
+ def __init__(self, attrs=None, choices=()):
+ super(LinkWidget, self).__init__(attrs)
+
+ self.choices = list(choices)
+
+ def value_from_datadict(self, data, files, name):
+ value = super(LinkWidget, self).value_from_datadict(data, files, name)
+ self.data = data
+ return value
+
+ def render(self, name, value, attrs=None, choices=()):
+ if value is None:
+ value = ''
+ final_attrs = self.build_attrs(attrs)
+ output = [u'<ul%s>' % flatatt(final_attrs)]
+ options = self.render_options(choices, [value], name)
+ if options:
+ output.append(options)
+ output.append('</ul>')
+ return mark_safe(u'\n'.join(output))
+
+ def render_options(self, choices, selected_choices, name):
+ def render_option(option_value, option_label):
+ option_value = force_unicode(option_value)
+ data = self.data.copy()
+ data[name] = option_value
+ try:
+ url = data.urlencode()
+ except AttributeError:
+ url = '?%s' % urlencode(data)
+ return '<a href="%s">%s</a>' % (url, option_label)
+ selected_choices = set(force_unicode(v) for v in selected_choices)
+ output = []
+ for option_value, option_label in chain(self.choices, choices):
+ if isinstance(option_label, (list, tuple)):
+ for option in option_label:
+ output.append(render_option(*option))
+ else:
+ output.append(render_option(option_value, option_label))
+ return u'\n'.join(output)
class RangeWidget(forms.MultiWidget):
def __init__(self, attrs=None):

0 comments on commit 88d7072

Please sign in to comment.
Something went wrong with that request. Please try again.