When using Django’s ModelChoiceField, with required=False, an extra choice ('', '--------') is generated automatically. When selecting this option, it ends up as None in the cleaned_data. How do I (idiomatically) reproduce this behavior when using a regular ChoiceField?
Some things I’ve noted:
- I have not found any way to automatically add the tuple
('', '---------')to the list ofchoices, so it appears to be required to add it manually. I feel there should be a way to add it to the choices by setting one of the parameters differently, so if that exists I would love to hear it. - The conversion from
''toNonemust still be done manually in the code that usescleaned_data. This means the code that deals withModelChoiceFields has to be subtly different from theChoiceFieldcode, which may possibly lead to subtle bugs. Again: if someone knows better idioms, I’d love to hear that. TypedChoiceFielddoes some magic handling of''. In particular, it does not offer it to thecoercefunction like one would expect.
Consider the following code:
def int_or_none(s):
if s.isnumeric():
return int(s)
return None
class NoneForm(forms.Form):
field = forms.TypedChoiceField(
choices=[('', '--------'), ('1', 'One'), ('2', 'Two')],
required=False, coerce=int_or_none)
def home(request):
if request.method == "POST":
form = NoneForm(request.POST)
if form.is_valid():
assert type(form.cleaned_data['field']) in [int, type(None)]
print form.cleaned_data['field']
form = NoneForm()
return HttpResponse(
"""<form method="POST">""" +
form.as_table() +
"""<input type="submit"></form>""")
The assertion above fails!
Can it really be this hard to get Django’s various versions of ChoiceField to clean to None in an idiomatic way?
This is the result based on rantanplan’s comment about the
empty_valueparameter.Note especially that the choice for the empty value is implemented as
''in the choices (just like inModelChoiceField, so that’s good).Now the assertion succeeds.