CheckBoxInput widget: check_test

1,045 views
Skip to first unread message

lingrlongr

unread,
Aug 6, 2010, 2:13:00 PM8/6/10
to Django users
Having difficulty getting the check_test to work. Can't find any
examples out there that help. I'll probably have to give a little
background. I simplified where able to...

class Cat:
name = CharField

class Category:
name = ForeignKey(Cat)
weight = DecimalField
item = ForeignKey('Item')

class Item:
name = CharField

Basically Cat is a model of all categories and Category is a model of
which Cat's are assigned to an item. I did it this way because I want
to have a "master list" of categories, then have the mapping done in
other models.

So now I want to build a form at run-time.

def get_form(item):
fields = dict()
cat_choices = [(c.id, c.name) for c in Cat.objects.all()]
for c in cat_choices:
id, name = c
checked = bool(item.categoty_set.filter(pk=id).count())

fields['item_cat_%d' % id] = forms.ChoiceField(
label = name,
required = False,
choices = cat_choices,
widget = forms.CheckboxInput(
attrs={'value': checked},
check_test = lambda a: a == checked
)
)
return type('CatSelectForm', (forms.BaseForm,), {'base_fields':
fields})

So how can I get the correct checkboxes checked at runtime when the
template is rendered?

Thx.

lingrlongr

unread,
Aug 6, 2010, 2:41:43 PM8/6/10
to Django users
Forgo the most important part. I want to be prompted with a
checkboxes that show which categories are selected, as well as the
ones that aren't.

Bill Freeman

unread,
Aug 6, 2010, 3:09:46 PM8/6/10
to django...@googlegroups.com
There is a CheckBoxSelectMultiple widget in django.forms, suitable
for use with a forms.ModelMultipeChoiceField, and probably with
other stuff. Doesn't it do what you need? Or are you just reinventing
the wheel.

And, of course, your code as shown doesn't work because Cat and
Category are not based on django.db.models.Model .

> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To post to this group, send email to django...@googlegroups.com.
> To unsubscribe from this group, send email to django-users...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
>
>

Daniel Roseman

unread,
Aug 6, 2010, 3:13:46 PM8/6/10
to Django users
The closure isn't acting the way you think. Each lambda is bound to
the same `checked` variable, whose value is changed each time through
the loop - so when it is actually evaluated, it has the value of the
last time through.

One way of fixing this is to use a nested function, rather than a
lambda, with a default value:
for c in cat_choices:
...
checked = bool(item.category_set.filter(pk=id).count())
def is_checked(a, checked=checked):
return a == checked
....
widget = forms.CheckboxInput(
attrs={'value': checked},
check_test = is_checked
)

This creates a new function each time, with the default parameter set
to the value of `checked` at the time it was defined.
--
DR.

lingrlongr

unread,
Aug 6, 2010, 3:26:38 PM8/6/10
to Django users
@Bill

Thanks. I just stumbled across that widget. I know models.Model
weren't there, I was trying to simplify thinking we'd all know they
were there. I guess, never assume ;)

Looks like I don't even have to worry about that check_test field
after all. Using initial worked perfectly.

def get_form(item):
fields = {}
choices = [(c.id, c.name) for c in Cat.objects.all()]
selections = [c.name.id for c in item.category_set.all()]
fields['cat'] = forms.MultipleChoiceField(
label=item,
required=False,
choices = choices,
initial=selections,
widget = forms.CheckboxSelectMultiple()
)
return type('CatForm', (forms.BaseForm,), {'base_fields': fields})
()




On Aug 6, 3:09 pm, Bill Freeman <ke1g...@gmail.com> wrote:
> There is a CheckBoxSelectMultiple widget in django.forms, suitable
> for use with a forms.ModelMultipeChoiceField, and probably with
> other stuff.    Doesn't it do what you need?  Or are you just reinventing
> the wheel.
>
> And, of course, your code as shown doesn't work because Cat and
> Category are not based on django.db.models.Model .
>

Bill Freeman

unread,
Aug 6, 2010, 3:58:31 PM8/6/10
to django...@googlegroups.com
It's always a hazzard to simplify the code because you can make errors
simplifying, causing folks to spend time trying to figure out the wrong
stuff. If the code is big it may be appropriate to excerpt, but other than
sanitizing out sensitive information, it's best not to edit the stuff you
do paste in.
Reply all
Reply to author
Forward
0 new messages