hidden fields not cleaned

1,274 views
Skip to first unread message

gentlestone

unread,
Mar 22, 2010, 10:31:48 AM3/22/10
to Django users
this piece of code leads to Key error 'some_hidden_field'

class XyForm(Form):

some_hidden_field =
forms.DateTimeField(widget=forms.HiddenInput())

def clean(self):
some_hidden_field = self.cleaned_data['some_hidden_field']

Why are hidden fields not cleaned?
I need to validate the hidden value and raise VadiationError if the
value is not ok.

Bjunix

unread,
Mar 22, 2010, 12:35:16 PM3/22/10
to Django users
Django validates form data in this order when calling is_valid or
full_clean:

1. run the clean method of the form field itself. Here:
DateTimeField.clean()
2. then run the clean_<fieldname>() method of the form if available
3. once those two methods are run for every field, run the clean()
method of the form

Source: http://docs.djangoproject.com/en/1.1/ref/forms/validation/#form-and-field-validation

So I guess the cleaned_data dict has no 'some_hidden_field' key.
DateTimeField.clean() probably raised a Validation Error and did not
populate the cleaned_data dictionary.

Try the following:

def clean(self):
cleaned_data = self.cleaned_data
#cleaned_data.get(key) returns None if key does not exist
some_hidden_field = cleaned_data.get("some_hidden_field")

if some_hidden_field:
#do your custom validation here and raise ValidationError
if necessary
# Always return the full collection of cleaned data.
return cleaned_data

gentlestone

unread,
Mar 23, 2010, 4:26:28 AM3/23/10
to Django users
I thought my def clean(self) is the third step in your explanation:

1. run the clean method of the form field itself. Here:
DateTimeField.clean()
2. then run the clean_<fieldname>() method of the form if available
3. once those two methods are run for every field, run the clean()
method of the form

So I believe Django has already run:
1. individual clean methods
2. the <fieldname>() methods (actualy don't have any)

and finally Django run MY OVERRIDED CLEAN method

I expect my some_hidden_field should be already successfuly cleaned
(whitout ValidateError exception) and included in cleaned_data.
Appareantly no, because the key error. So this is propably a bug I
think.

If I changed the problematic line
forms.DateTimeField(widget=forms.HiddenInput())
to
forms.DateTimeField()
everything run whitout problems. Just my hidden field is'nt hidden.
This is the state of my application now.

On 22. Mar., 17:35 h., Bjunix <bju...@bjunix.de> wrote:
> Django validates form data in this order when calling is_valid or
> full_clean:
>
> 1. run the clean method of the form field itself. Here:
> DateTimeField.clean()
> 2. then run the clean_<fieldname>() method of the form if available
> 3. once those two methods are run for every field, run the clean()
> method of the form
>

> Source:http://docs.djangoproject.com/en/1.1/ref/forms/validation/#form-and-f...

Bjunix

unread,
Mar 23, 2010, 5:57:57 AM3/23/10
to Django users

> I thought my def clean(self) is the third step in your explanation:


Yes that's right. But this clean methods gets called even if your
Field raised a ValidationError. Validation errors are hold back until
the clean method returns the cleaned_data dict. Try to 'get' the key
(not calling it directly) with cleaned_data.get(<fieldname>) and let
your clean method return cleaned_data and see if a ValidationError was
raised earlier. Django did not put your hidden field into cleaned data
probably because the hidden field value is just not clean. So, I dont
think its a bug in django.

Maybe the hidden input has the wrong format or it's empty. Can you
show the data you populate your hidden field with?

gentlestone

unread,
Mar 23, 2010, 7:13:04 AM3/23/10
to Django users
oh, great, you were right, thank you

"Validation errors are hold back until the clean method returns the
cleaned_data dict."

really the some_hidden_field was invalid, I included {{ form.errors }}
to my template and the validation error appeared suddenly :-)

What I still don't understand, why this piece of code

form = XyForm(initial = dict(
some_hidden_field = datetime.now(),
))

works with
forms.DateTimeField()
and doesn't work with
forms.DateTimeField(widget=forms.HiddenInput())

If the field is hidden, the initial value is invalid and is not
cleaned. Why?

gentlestone

unread,
Mar 23, 2010, 7:30:32 AM3/23/10
to Django users
I'll try to answer myself :-)

because widget=forms.HiddenInput() is invalid widget for
DateTimeField.

Changed in Django 1.0: The DateTimeField used to use a TextInput
widget by default. This has now changed.

So I left the original DateTimeInput for this field and used
{{ form.some_hidden_field.as_hidden }} in the template

It was almost correct, with a little help with

http://code.djangoproject.com/ticket/9459

everything is ok.

May be this discussion helps to someone ...

Reply all
Reply to author
Forward
0 new messages