Opened 17 years ago

Last modified 14 years ago

#5327 closed

ChoiceField clean method — at Version 4

Reported by: danielrubio Owned by: Philippe Raoult
Component: Documentation Version: dev
Severity: Keywords: ChoiceField clean method id
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Malcolm Tredinnick)

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:

 def clean(self, value):
        """
        Validates that the input is in self.choices.
        """
        value = super(ChoiceField, self).clean(value)
        if value in EMPTY_VALUES:
            value = u''
        value = smart_unicode(value)
        if value == u'':
            return value
        valid_values = set([smart_unicode(k) for k, v in self.choices])
        if value not in valid_values:
            raise ValidationError(ugettext(u'Select a valid choice. That choice is not one of the available choices.'))
        else:
            value = self._choices[int(value)][1]
        return value

Only modification is the 'else' at the end, which would assign the value to the actual string.


Change History (5)

comment:1 by danielrubio, 17 years ago

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.'))

else:

for k, v in self.choices:

if(smart_unicode(k) == value):

return smart_unicode(v)

comment:2 by Philippe Raoult, 17 years ago

Needs documentation: set
Owner: changed from nobody to Philippe Raoult
Triage Stage: UnreviewedDesign decision needed

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.

by Philippe Raoult, 17 years ago

Attachment: 5327.diff added

clarification of the docs concerning ModelChoices

comment:3 by Philippe Raoult, 17 years ago

Has patch: set
Needs documentation: unset
Status: newassigned
Triage Stage: Design decision neededReady for checkin

comment:4 by Malcolm Tredinnick, 17 years ago

Description: modified (diff)

(fixed description formatting)

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