Opened 16 years ago

Closed 9 years ago

Last modified 9 years ago

#9230 closed New feature (duplicate)

Iterating over checkboxes in CheckboxSelectMultiple should be possible

Reported by: Malcolm Tredinnick Owned by: Malcolm Tredinnick
Component: Forms Version: 1.0
Severity: Normal Keywords:
Cc: Ben Spaulding, Reto Aebersold, bmispelon@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Right now, if you have a form field that is using the CheckboxSelectMultiple widget, there's no way in a template (or even in Python code) to iterate over the constituent pieces. This is a missing feature, since it prevents designers or designer-targeted template tags from working with the "bits".

This is a feature-add, not a piece of broken functionality, so it's only for trunk.

Attachments (1)

forms.py.diff (1.9 KB ) - added by Reto Aebersold 15 years ago.
Iterating over choice widgets

Download all attachments as: .zip

Change History (18)

comment:1 by Ben Spaulding, 16 years ago

Cc: Ben Spaulding added

comment:3 by Eric Holscher, 15 years ago

Triage Stage: UnreviewedAccepted

I trust malcolm and ben know what they're talking about. Setting to accepted :)

comment:4 by Rob Hudson <treborhudson@…>, 15 years ago

I just hit a use-case where this would be nice, so a +1 as a feature request from me. The workaround posted wasn't helpful... I want to customize the display of the label tag given the choices object, so it's not the default __unicode__ output, but something else.

comment:5 by lbolognini, 15 years ago

This would be a nice to have feature: right now i wanted to display an image next to each checkbox part of this widget.

comment:6 by BradMcGonigle, 15 years ago

I also just ran into a use-case for this so another +1.

comment:7 by DataGreed, 15 years ago

+1
I cannot design nrmally a nice Two-Column list of checkboxes

comment:8 by Reto Aebersold, 15 years ago

Has patch: set
Needs tests: set

I wrote a small patch to solve this problem. Needless to say that we have to update all the 'choice' widgets the provide a solid solution.
This is a minimal solution intended as a basis for discussion.
An iteratable widget could look like this:

class MyCheckboxSelectMultiple(CheckboxSelectMultiple):
    
    def get_iterator(self, name, value, attrs):
        """
        Alternatively we could pre-render here all the choices and store them in a list. 
        """
        self.item = 0
        self.name = name
        self.attrs = attrs
        if value is None: value = []
        self.value = value        
        self.str_values = set([force_unicode(v) for v in value])
        self.has_id = attrs and 'id' in attrs
        self.final_attrs = self.build_attrs(attrs, name=name)        
        return self
    
    def next(self):
        
        if self.item >= len(self.choices):
            raise StopIteration
        
        if self.has_id:
                final_attrs = dict(self.final_attrs, id='%s_%s' % (self.attrs['id'], self.item))
                label_for = u' for="%s"' % final_attrs['id']
        else:
            label_for = ''
        
        (option_value, option_label) = self.choices[self.item]
        cb = CheckboxInput(final_attrs, check_test=lambda value: value in self.str_values)
        option_value = force_unicode(option_value)
        rendered_cb = cb.render(self.name, option_value)
        option_label = conditional_escape(force_unicode(option_label))
        
        self.item += 1
        return mark_safe(u'<label%s>%s %s</label>' % (label_for, rendered_cb, option_label))

by Reto Aebersold, 15 years ago

Attachment: forms.py.diff added

Iterating over choice widgets

comment:9 by Reto Aebersold, 15 years ago

Cc: Reto Aebersold added

comment:10 by Luke Plant, 13 years ago

Severity: Normal
Type: New feature

comment:11 by skylar.saveland@…, 12 years ago

Easy pickings: unset
UI/UX: unset

this comes up all the time for me. I use this nasty widget that I made: http://skyl.org/log/post/skyl/2011/01/wherein-the-inner-workings-of-the-deathstarwidget-are-revealed/

comment:12 by Skylar Saveland, 12 years ago

I have been told that this works: http://djangosnippets.org/snippets/2159/

comment:13 by Baptiste Mispelon, 11 years ago

Cc: bmispelon@… added
Resolution: duplicate
Status: newclosed

Unless I'm mistaken, this is a duplicate of #4592.

comment:14 by Gerben Morsink, 9 years ago

This is my first post here, so sorry if I'm doing it wrong.

I'm trying to iterate over my checkboxes (using Django 1.7.7) where I'm using an ModelFormSet to generate multiple forms.

My original code is:

{%if field.name == "repeat_weekday" %}
     <td>{{field}}<td>
 {% endif %}

Now I have made:

{% for choice, choice_label in field.field.widget.choices %}
                        <td> <input checked={{choice.checked}} id="id_form-0-repeat_weekday_0" name="form-0-repeat_weekday" type="checkbox" value="{{ choice }}"> {{choice_label}} </td>
                    {% endfor %} 

but I don't know how to find the = checked and id and name via the field.

Easier would IMO be to do something like the thing below (and I would say that would be a genuine fix of the issue in this ticket):

{% for checkbox, label in field.checkboxes %}
{{ checkbox }}   <!-- Renders the checkbox completely
{{ label }} <!-- Renders the label completely
{% endfor %}

Ok, found the documentation: https://docs.djangoproject.com/en/1.7/ref/forms/widgets/#django.forms.RadioSelect

However, if I update my template to:

            {% for field in form.visible_fields %}

                {% for checkbox in field.repeat_weekday %}
                   <td>{ {field} }<td>

                {% endfor%}

            {% endfor %}

It still does not work.

Version 2, edited 9 years ago by Gerben Morsink (previous) (next) (diff)

comment:15 by Gerben Morsink, 9 years ago

Resolution: duplicate
Status: closednew

I have checked the documentation a 100 times, but for me it does not work as expected.

The {{field.repeat_weekday}} is always empty in my template, so looping over it wont work to create the checkboxes.

I have overriden the render method in my widget, but that should not matter I think since I only change the value and then call the original render:

class BinaryMultipleSelectBox(forms.CheckboxSelectMultiple):
    def render(self, name, value, attrs=None, choices=()):
        if value is None:
            value = []
        else:
            value = TemplateEventMeta.WEEKDAYS.get_selected_values(value)
        return forms.CheckboxSelectMultiple.render(self, name, value, attrs=attrs, choices=choices)
Last edited 9 years ago by Gerben Morsink (previous) (diff)

comment:16 by Baptiste Mispelon, 9 years ago

Resolution: duplicate
Status: newclosed

Hi,

The best place to go for questions like these would rather be the django-users mailing list: https://groups.google.com/forum/#!forum/django-users.

Thanks.

comment:17 by Claude Paroz <claude@…>, 9 years ago

In 97e1160:

Refs #9230 -- Added complementary tests for widget iterations

Note: See TracTickets for help on using tickets.
Back to Top