Login

Widget for CommaSeparatedIntegerField with pre-defined choices

Author:
rudyryk
Posted:
June 4, 2010
Language:
Python
Version:
1.2
Tags:
forms widget comma-separated
Score:
3 (after 3 ratings)

Widget for editing CommaSeparatedIntegerField with a set of checkboxes. Each checkbox corresponds to single integer value. So, choices should be pre-defined for widget.

Example

Assume, we need a registration form for some event with time frame for 3 days, starting at Monday. User can select any of 3 days, so we need to show 3 checkboxes.

Here's the basic example for such form:

class EventRegistrationForm(forms.Form):
    days = forms.CharField(widget=NumbersSelectionWidget(
                    ['Mon', 'Tue', 'Wed'], range(1, 4)))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from django.forms.widgets import Widget
from django.forms.util import flatatt
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe

class CheckboxesForCommaSeparated(Widget):
    def __init__(self, choices, attrs=None, renderer=lambda x: mark_safe(u'\n'.join(x))):
        super(CheckboxesForCommaSeparated, self).__init__(attrs)
        self.choices = choices
        self.renderer = renderer
    
    def decompress(self, value):
        return value.split(',')
    
    def render(self, name, value, attrs=None):
        if value is None:
            value = ''
        output = []
        selected = self.decompress(value)
        has_id = attrs and 'id' in attrs
        for i, v in enumerate(self.choices):
            final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
            final_attrs['value'] = force_unicode(v)
            if str(v) in selected:
                final_attrs['checked'] = 'checked'
            if has_id:
                final_attrs['id'] = '%s_%s' % (attrs['id'], i)
            output.append(u'<input%s />' % flatatt(final_attrs))
        return self.renderer(output)
    
    def value_from_datadict(self, data, files, name):
        values = data.getlist(name)
        return ','.join(values) if values else ''

class NumbersSelectionWidget(CheckboxesForCommaSeparated):
    def __init__(self, labels, *args, **kwargs):
        self.labels = labels
        kwargs['renderer'] = self.render_with_labels
        super(NumbersSelectionWidget, self).__init__(*args, **kwargs)
    
    def render_with_labels(self, checkboxes):
        output = []
        output.append('<table>')
        output.append('<tr>')
        for i, c in enumerate(checkboxes):
            output.append('<td>%s</td>' % self.labels[i % len(self.labels)])
        output.append('</tr>')
        output.append('<tr>')
        for i, c in enumerate(checkboxes):
            output.append('<td>%s</td>' % c)
        output.append('</tr>')
        output.append('</table>')
        return mark_safe(u'\n'.join(output))

More like this

  1. CheckboxMultiSelect with interable checkboxes by pyramids16 2 years, 9 months ago
  2. A Lazy ModelChoiceField implementation by alecdotico 2 years ago
  3. MultiSelect checkbox iterator template filter by ke1g 4 years, 11 months ago
  4. Readonly Select Widget Replacement by colinkingswood 7 months, 3 weeks ago
  5. ModelForm Class saving m2m by ckarrie2 3 years, 9 months ago

Comments

Please login first before commenting.