pythondjango

Django MultipleChoiceField not sending valid data in POST


My django form has a field MultipleChoiceField in with a list of tuples as the options.

choice = forms.MultipleChoiceField(
    choices = [("1", "Option 1"), ("2", "Option 2"), ("3", "Option 3")],
    label="Choose an option",
    widget=forms.Select(),
    required=True,
)

This creates the DOM element when it is loaded

<select name="choice" id="id_choice">
  <option value="1">Option 1</option>
  <option value="2">Option 2</option>
  <option value="3">Option 3</option>
</select>

However, when it sends the POST request on the form being submitted, instead of giving a value ("1", "Option 1"), it just sends "1". As such, this triggers a ValidationError in the MultipleChoiceField when it is validated, as it has this function which requires the POST value to be a list or a tuple.

def to_python(self, value):
    if not value:
        return []
    elif not isinstance(value, (list, tuple)):
        raise ValidationError(
            self.error_messages["invalid_list"], code="invalid_list"
        )
    return [str(val) for val in value]

Is there any way of setting the POST value of the DOM element so that it sends this tuple?

I tried to change it in the views.py function using field.data, but got This QueryDict instance is immutable

Thanks in advance.


Solution

  • It should not raise an error, the reason it expects a list is because it works with .getlist(…) [Django-doc] from the data, and because multiple in the `MultipleChoiceField.

    The reason it errors, is because you use a Select widget [Django-doc], whereas it should be a SelectMultiple widget [Django-doc], so:

    choice = forms.MultipleChoiceField(
        choices=[('1', 'Option 1'), ('2', 'Option 2'), ('3', 'Option 3')],
        label='Choose an option',
        widget=forms.SelectMultiple(),
        required=True,
    )