Opened 8 years ago

Closed 8 years ago

#27578 closed Bug (invalid)

ModelChoiceField.to_python() somehow receives value as type 'list'

Reported by: Julian Owned by: nobody
Component: Forms Version: 1.9
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Julian)

Whenever im running form.is_valid() i get the error:

Select a valid choice. That choice is not one of the available
choices.

Here is what I do in my view:

    timeframes = HostTimeFrame.objects.all()
    if request.method == 'POST':
        form = SelectDatesForm(request.POST, timeframes=timeframes)
        if form.is_valid():
            pass
    else:
        form = SelectDatesForm(timeframes=timeframes)

My form does this:


  class SelectDatesForm(forms.Form):
        timeframes = forms.ModelChoiceField(queryset=HostTimeFrame.objects.none(), widget=forms.CheckboxSelectMultiple,
                                            empty_label=None)
        def __init__(self, *args, **kwargs):
            qs = kwargs.pop('timeframes')
            super(SelectDatesForm, self).__init__(*args, **kwargs)
            self.fields['timeframes'].queryset = qs.order_by('start')

Ive been trying for hours to find where this actual validation is done, and realized the exception is raised in ModelChoiceField.to_python()

        try:
            key = self.to_field_name or 'pk'
            value = self.queryset.get(**{key: value})
        except (ValueError, TypeError, self.queryset.model.DoesNotExist):
            raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')

Where value is the primary key, but in List format, this raises an exception.

Change History (3)

comment:1 by Julian, 8 years ago

Description: modified (diff)

in reply to:  1 comment:2 by Julian, 8 years ago

Replying to Julian Schneider:
Created my own bugfixes in a custom field:

class CustomModelChoiceField(ModelChoiceField):
    def to_python(self, value):
        if value in self.empty_values:
            return None
        try:
            key = self.to_field_name or 'pk'
            if type(value) == list:
                value = value[0]
            value = self.queryset.get(**{key: value})
        except (ValueError, TypeError, self.queryset.model.DoesNotExist):
            raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')
        return value

comment:3 by Tim Graham, 8 years ago

Resolution: invalid
Status: newclosed

If you're using widget=forms.CheckboxSelectMultiple then you need to use ModelMultipleChoiceField which accepts a list of values.

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