Opened 11 years ago

Closed 11 years ago

Last modified 10 years ago

#20800 closed Bug (needsinfo)

validation error does not give hint of type mismatch for choices

Reported by: Preston Holmes Owned by: nobody
Component: Forms Version: dev
Severity: Normal Keywords: validation
Cc: eromijn@…, Salem.Mike.Z.@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

If you have a choices list of ((0, 'label'),) set to a charfield though 1.5 you would get a validation error that looked like:

Value u'0' is not a valid choice.

Currently you get a validation error of:

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

This is less helpful as the displayed error does not indicate the type.

The user generally doesn't know about the value part of choices, so this was always confusing to users - but that part is not new and is not related to this regression.

Change History (5)

comment:1 by Sasha Romijn, 11 years ago

Cc: eromijn@… added
Easy pickings: set

So, why was this changed? There has to be a commit somewhere, possibly with a ticket referred. Perhaps there were good reasons why this was changed.

comment:2 by Preston Holmes, 11 years ago

I'm guessing this was an unintended by-product of some sort of py2/3 text handling, but not sure. The error string itself changed, but I don't think that commit is what resulted in this.

It is a classic case for using git bisect.

comment:3 by anonymous, 11 years ago

Resolution: needsinfo
Status: newclosed

The two error messages noted are coming from different level of the code, this is not a case where one error message was changed to another but perhaps a case where somehow a path through the code has changed and now a different error message is being shown as a result. However from the description I can't tell under what circumstances exactly the change has been observed. The first variant noted above is the default message for the "invalid_choice" error at the model field level:

https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L71

The 2nd variant is the default "invalid_choice" message for the form ChoiceField type:

https://github.com/django/django/blob/02b0106d43f6997f02cc6785359f8f7519215d3d/django/forms/fields.py#L751

Depending on how I "clean" data I can still see the different error messages with current master level (Book has a genre CharField with choices=((0, 'Sci-Fi'), (1, 'Mystery'))...which yes is a completely broken choices value for a CharField but makes it nice and easy to trigger these error messages):

>>> import django
>>> from django import forms
>>> django.get_version()
'1.7.dev20130728080539'
>>> from ttt.models import Book
>>> bbb = Book(genre=1)
>>> bbb.full_clean()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/kmtracey/django/git-django/django/db/models/base.py", line 957, in full_clean
    raise ValidationError(errors)
ValidationError: {'genre': [u"Value u'1' is not a valid choice."], 'name': [u'This field cannot be blank.'], 'author': [u'This field cannot be null.']}
>>> class BookForm(forms.ModelForm):
...     class Meta:
...         model = Book
... 
<string>:1: DeprecationWarning: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is deprecated - form BookForm needs updating

>>> bf = BookForm({'genre': 1})
>>> bf.errors
{'genre': [u'Select a valid choice. 1 is not one of the available choices.'], 'name': [u'This field is required.'], 'author': [u'This field is required.']}
>>> 

Could you describe under what circumstances exactly you are seeing the 2nd variant where in the past you used to see the 1st?

comment:4 by Preston Holmes, 11 years ago

This was seen in the admin, for a CharField that was set to uses a choices iterable with int choices.

comment:5 by Salem.Mike.Z.@…, 10 years ago

Cc: Salem.Mike.Z.@… added

Just writing to say ditto; pretty much the same exact scenario as described.

I changed a model field to use choices, spent an hour trying to figure out why my choices weren't available, then realized I had forgotten to change the field's type from int to char. If it weren't for the fact that I had other fields using choices in the same model (which weren't giving me problems) I probably would have given up and decided to go another route.

Sorry I don't have the time to get into the Django dev world at this time but perhaps this should be a request to add some model validation? A choice is of the wrong type? Or no choice is valid and blank=False? I'd be glad to re-write this in that format if that would help.

Thanks

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