form with CheckboxSelectMultiple doesn't validate - django

I have a form with a choice field that is using CheckboxSelectMultiple widget:
foo = forms.ChoiceField(widget=forms.CheckboxSelectMultiple,
choices=(
("1", "ONE"),
("2", "TWO"),
))
The form renders fine showing two checkboxes, however it doesn't validate.
If I select both checkboxes I am getting an error: Select a valid choice. [u'1', u'2'] is not one of the available choices
Selecting one checkbox doesn't work either, it gives me: Select a valid choice. [u'1'] is not one of the available choices.
What's going on here?

If you make the field a forms.MultipleChoiceField rather than a forms.ChoiceField it will work better.

May this helpful for you
num_choices = ( ("1", "ONE"), ("2", "TWO"), ("3", "Three"), ("4", "Four"))
num_list = forms.MultipleChoiceField(choices=num_choices, required=True, widget=forms.CheckboxSelectMultiple(), label='Select No', initial=("1", "2"))
If you want to pass the ORM object directly, then you can try the following
num_list = forms.ModelMultipleChoiceField(Numbers.objects.all(), required=True, widget=forms.CheckboxSelectMultiple(), label='Select No')

Related

How to add disable attribute to a Django <select> form?

I have a Django choice form:
SEASON_CHOICES = (
('running', 'Running season'),
('next', 'Next season' )
)
class DeterminingForm(forms.Form):
season = forms.ChoiceField(widget=forms.Select, choices=SEASON_CHOICES)
I want a disabled option in my form. Something like a placeholder with 'Choose an option', just like you see on almost any select form. I don't know how to do this. Any idea?

Django choicefield choices not displaying

Im using a choicefield and setting 2 values - 'students', 'teachers',
but for some reason when the form displays it only shows 'teachers' and not 'students'.
class SignUpShortForm(SignUpForm):
role = forms.ChoiceField(
choices=[],
widget=forms.Select(attrs={'class':'form-control'}),
label='I am a...',
)
self.fields['role'].choices = [('Teacher', 'Teacher2')]
Please look here You add to your choices only values without keys. Code might look like this:
CHOICES = (
('students', 'Students'),
('teachers', 'Teachers'),
)
class SignUpShortForm(SignUpForm):
role = forms.ChoiceField(
choices=CHOICES,
widget=forms.Select(attrs={'class':'form-control'}),
label='I am a...',
)

Form not working with more than 10 choices using CommaSeparatedIntegerField in Django

After following the rather useful blog post, I am having issues with the widget (forms.SelectMultiple or forms.CheckboxSelectMultiple) not correctly showing which choices have previously been selected, if the number of choices is > 9.
Model:
from django.db import models
class Flower(models.Model):
'''Flowers'''
flowers = models.CommaSeparatedIntegerField(max_length=100, default="1,2", blank=True)
Form:
from django import forms
class FlowerForm(forms.ModelForm):
FLOWERS = (
('0', 'Daisies'),
('1', 'Petunias'),
('2', 'Roses'),
('3', 'Forget-me-nots'),
('4', 'Choice 4'),
('5', 'Choice 5'),
('6', 'Choice 6'),
('7', 'Choice 7'),
('8', 'Choice 8'),
('9', 'Choice 9'),
('10', 'Choice 10'),
('11', 'Choice 11'),
('12', 'Choice 12'),
('13', 'Choice 13'),
)
flowers = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple, choices=FLOWERS, initial="1")
def clean_flowers(self):
field = ""
for data in self.cleaned_data['flowers']:
field += str(data)+","
return field.lstrip(",")
If you select any choices in the list, it does correctly save to the database (via the cleaning function), but when you go back to the form choices above 9 are no longer selected. Other choices are marked as selected instead - choice 1 and the value-10; e.g. if you choose choice 13, choices 1 & 3 will be selected when going back to the form
Please help!?!
Edit: FYI, I'm using Django 1.8.3 with Python 3.4.0.
I think the problem is when you convert the list to a comma separated string in your clean method... it looks like this value is then used by Django when displaying the form.
It seems Django is expecting a list and iterating over the field value, so when you pass it say '13' Django will select '1' and '3' (because strings are iterable as lists of characters)
So there's a problem matching what the form expects (list of values) with what the db field expects (comma separated string)
I don't think there is a straightforward solution.
Maybe try something like this snippet with custom db field as a starting point:
https://djangosnippets.org/snippets/2753/
With thanks to the link from Anentropic, one of the comments on the linked page was for someone who has expanded that snippet into django-multiselectfield: https://pypi.python.org/pypi/django-multiselectfield/0.1.3
I've installed that, changed my model to use that new MultiSelectField fieldtype, and it all works. Many thanks to Anentropic for getting me there.
Shame about the poorly documented CommaSeparatedIntegerField fieldtype though.

ModelForm in template with a grouped choice field

I have a grouped category field. The problem is that I've created a search form, but when I try presente the form to the user in the template, it goes wrong.
models.py
MEDIA_CHOICES = (
('Audio', (
('vinyl', 'Vinyl'),
('cd', 'CD'),
)
),
('Video', (
('vhs', 'VHS Tape'),
('dvd', 'DVD'),
)
),
('unknown', 'Unknown'),
)
category = models.CharField(max_length=20, choices=MEDIA_CHOICES, verbose_name=_(u'Category'))
forms.py (search)
class SearchingForm(forms.Form):
"Search Box"
search = forms.CharField(max_length=100, required=False, label=(_(u'Search')))
music_kind = forms.MultipleChoiceField(choices=MEDIA_CHOICES, required=False,
label=(_(u'Kind')),
widget=forms.CheckboxSelectMultiple(),
)
template.html
{{ form.search }}
{{ form.place_kind }}
I show the form to the user like this, the problem is when I rendered with a browser I have something like this (in each line, it has a checkbox):
(('vinyl', 'Vinyl'), ('cd', 'CD'))
(('vhs', 'VHS Tape'), ('dvd', 'DVD'))
Unknown
I have delete the 'widget=forms.CheckboxSelectMultiple()' attribute it goes right, but I don't have a checkboxes. So, How I can do it with checkbox fields?
I think you have a data type mismatch here. You're wanting to store multiple values in a single CharField. Sure, you could save a dictionary of key-value pairs in there, but then you'd have to parse it back out into selections, and that's a huge pain.
I would move your MEDIA_CHOICES to a database table, and then in your SearchingForm, you can do a CheckboxSelectMultiple, and the form will behave as expected.
I'm not sure, but I wonder if choice groups are only for select boxes (not checkboxes).

Django ChoicesField divider?

I'm using a ChoicesField in my form, but I want to put a divider in it like this:
COUNTRIES = (
('CA', _('Canada')),
('US', _('United States')),
(None, _('---')), # <----------
('AF', _('Afghanistan')),
('AX', _('Aland Islands')),
('AL', _('Albania')),
('DZ', _('Algeria')),
('AS', _('American Samoa')),
# ...
class AddressForm(forms.Form):
country = forms.ChoiceField(choices=COUNTRIES, initial='CA')
What's the easiest way to make that unselectable, or at least give an error if the user picks it?
You can use this: https://docs.djangoproject.com/en/dev/ref/models/fields/#field-choices
You would format it like this:
COUNTRIES = [
("CA", _("Canada")),
("US", _("United States")),
# This format will indent the nested tuples over and the
# "-----" will be un-selectable
#
("---------------", ( # This will be a header for the items nested below
("AF", _("Afghanistan")),
('AX', _('Aland Islands')),
('AL', _('Albania')),
('DZ', _('Algeria')),
('AS', _('American Samoa')),
)
),
]
You could write a clean method to raise a validation error if any divider is selected.
class AddressForm(forms.Form):
country = forms.ChoiceField(choices=COUNTRIES, initial='CA')
def clean_country(self):
data = self.cleaned_data["country"]
if not data:
raise forms.ValidationError("You must select a valid country.")
return data
I don't know what version of Django you are using, but I am on 1.10.1 and I used the following:
ICONS = (
(None, ''),
(None, '==Extra Contact Info=='),
('phone', 'Phone'),
('phone', 'Phone (square)'),
('fax', 'Fax'),
('envelope', 'E-mail (black)'),
('envelope-o', 'E-mail (white/clear)'),
(None, ''),
(None, '==Social Media=='),
('facebook', 'Facebook'),
('facebook-official', 'Facebook (official)'),
('facebook-square', 'Facebook (square)'),
('google-plus', 'Google Plus'),
...
)
and that's all I used, and if a user selects any list item in a drop-down menu that has a 'None' value in it, it will bark at the user saying "This field is required."
Now... of course in my project, the choices list is being used in my whatever.com/admin page, but that may not be relevant. What is relevant however, is that you have to ensure your model (or form) class field does not contain "blank = True". By default it should be false if you omit it, in other words the field won't accept null or empty string values. That should be all you need...