Django Forms – ChoiceField and MultipleChoiceField


Well, I have been working on my latest project for a client in Django for a couple weeks now in my spare time. I enjoy it a lot!  The documentation is great, but there isn’t enough of it yet.

My day job is mostly Microsoft based development and I must say it makes me lazy, because the great amount of resources out there. If I encountered a problem someone has solved it or can give a tremendous amount of insight to solve the issue.

Looking at the Django community since version 1 of the web framework, you get a sense it is going to be great and is only a matter of time before resources grow.

To the point MAN!!!!

One thing I wasted a a couple hours on was using a CheckBox with Multiple selections, what isn’t documented clearly is when to use ChoiceField or MultiChoiceField. In retrospect seeing ChoiceField and seeing MultipleChoiceField side by side, the decision is obvious.  However, at first glance and examples I have seen, I didn’t know that MultipleChoiceField was an option. I thought I could use ChoiceField with widget=forms.CheckboxSelectMultiple, like this:

class QuestionMulipleSelect(forms.Form):
    answers = forms.ChoiceField(widget=forms.CheckboxSelectMultiple, label="")
.
.
.

This will render the form fine, but when you do a post you will always get an invalid selection error … you must use MultipleChoiceField like:
class QuestionMulipleSelect(forms.Form):
    answers = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, label="")
.
.
.

This will render and post just the way expected.
The thing to remember is any widget that returns a scalar value uses: ChoiceField.
When you using a widget with mutli selection then you must use: MultipleChoiceField. The details of instantiating them are the same, retrieving the values are a little different; MultipleChoiceField has a list as the value attribute and ChoiceField is scalar.

Short tip for now, if anybody wants a code example, I will be happy to update this post with a more detailed example.

Cheers and Beers!

Fritz


4 Comments on “Django Forms – ChoiceField and MultipleChoiceField”

  1. Martin says:

    Hi Fritz,

    I would love to see some example code on how to handle the submission in a view!

    Cheers…

    • ontehfritz says:

      Well django does most of the work for you when setup correctly.

      you have a view like so:

      def render_questions(request):
      .
      .  Some code here 
      .
      
         if request.method == 'POST':
              form_list = create_question_forms(request.POST)
      
              for form in form_list:
                  if form.is_valid():
                      form.save()
                  
              return HttpResponseRedirect(some_url) #direct to url after
          else:
                  form_list = create_question_forms()
      
          return render_to_response('your_template.html', {'forms': form_list})
      

      the request.POST on submit contains a QueryDict object that contains all of your submitted data, so pass this to your create_question_forms object, which is defined like this:

      def create_question_forms(data=None):
          question_list = ... # get all your questions from here via db or where ever your questions are stored
          form_list = []
         
         for pos, question in enumerate(question_list):
                  #data is the request.POST and if it is there will populate you questions with the user choices
                  form_list.append(QuestionMulipleChoiceRadio(question, data, prefix=pos))
      
          return form_list
      

      Then your Question form would be something like this:

      class QuestionCheckBox(forms.Form):
          answers = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, label="")
          def __init__(self, question, *args, **kwargs):
              super(QuestionCheckBox, self).__init__(*args, **kwargs)
              self.text = question.text
              self.question = question
           
              answers = question.answer_set.all().order_by('index')
              self.fields['answers'].choices = [(str(i), a.text) for i, a in enumerate(answers)]
              self.choices_dict = dict(self.fields['answers'].choices)
              self.count = count
      
          def save(self, commit=True):
            ...
            Some more code, do what you want
            ....
      

      Confusing huh? Well as much detail as I can get into right now. But basically when the user submits the data with the post.Tehn you pass the post to the view; then pass that data to your form and it will rebuild it with the data from the request.POST; then once the form is valid and the save method is called. You can save it to where ever you like DB, XML and JSON file whatever it is up to you. Hope this helps!

  2. Henry says:

    Hi:
    I would like to know how do I get the selected objects in a MultipleChoiceField after the form is submited

    Thanks, By


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.