Using both ChoiceField and ModelChoiceField, I discovered a bug in ChoiceField clean method ( or a discrepancy in behaviour)

ModelChoiceField seems to be working as expected, when I call the clean method in a template like so: form.clean.city , I get the city name(e.g New York), or what would be string inside the tag <select id="5"> New York </select>

This behaviour is different if the values are inside a ChoiceField, if I use the following in the template: form.clean.city, I get the city id (e.g 5 ), not the expected string or behaviour as using ModelChoiceField.

[NOTE: Not calling the clean field, in either !ChoiceField or !ModelChoiceField works identcally, generating a select list ]

I modified the fields.py file in django/newforms, the clean method on the ChoiceField class[line 466], would now read:

Change History (14)

Did some more testing, the previous fix assumed the option keys were in order 1,2,3,4,5,6,7,8,9.etc.. I had a list ordered by name, and the previous code obviosuly gave the wrong key value. The following snippet will fix this.

if value not in valid_values:

raise ValidationError(ugettext(u'Select a valid choice. That choice is not one of the available choices.'))

Logically the model choicefield should be able to return either an object or just its id, but that should be more explicit in the docs (it is not explicitely listed in the FormField list). Also, the ChoiceField doc doesn't say if the first or second member of the choice tuple is used as the normalized value.

We should resolve the inconsistency here, I suspect. My gut feeling is that cleaning to the id value is more correct, because that is what you would assign to a field that had "choices" as an option. But whichever way we go, I'm not too comfortable with the inconsistency. ModelChoiceField subclasses ChoiceField, so it shouldn't behave wildly differently.

ModelChoiceField will NOT return a name, it will return the object associated with the id you selected. The only difference with a ChoiceField is that ModelChoiceField will resolve the object from the id in the queryset, which is to be expected given the field name. There is no inconsistency here, and the patch only clarifies the current documentation.