Hi folks

After my previous post about a KeyError after a form validation failure,
I've now narrowed down the behaviour change in pylons 0.9.7 from 0.9.6, and
what might be causing it.  I believe this change is incorrect.  I've also
included a minimal test case to reproduce the issue.

When using the @validate decorator to validate a form submission using
formencode, validation failure causes the request to be forwarded to the
form display method specified by the 'form' argument to the decorator, as a
GET.  Examining the contents of request.params in the form display method
after a validation failure, *only GET parameters* are present - none of the
POST parameters are available.

This means that a form requiring extra parameters that are still present on
validation failure must supply these as GET parameters (via the POST URL for
the form) - including them as hidden fields in the form will not work.  This
is a change in behaviour from 0.9.6, where the POST parameters were still
available on validation failure.

I believe that the 0.9.6 behaviour is the correct one - the proper
parameters are those submitted by the request which were valid *when
parsed*, not those which would apply when the submit method is changed from
POST to GET later on.

It's easy to reproduce this, using a minimal controller and template based
on the Form Handling page on the Wiki.  With the code below, submitting the
form at /form/form with no email address prints out:
    Params from display method: UnicodeMultiDict([('avar', u'dummy')])
i.e. the parameter from the URL.  Note that the hidden field from the form
isn't present.

Submitting the form again with a valid email address prints:
    Params from submit method: UnicodeMultiDict([('avar', u'dummy'),
('email', u'[email protected] <u%[email protected]>'), ('submit', u'Submit'),
('hidden', u'Hidden')]).
i.e. now both the GET and POST parameters are present.

form.py:
-----------
import logging

from pylons import request, response, session, tmpl_context as c
from pylons.controllers.util import abort, redirect_to
from helloworld.lib.base import BaseController, render, validate

log = logging.getLogger(__name__)

import formencode

class EmailForm(formencode.Schema):
    allow_extra_fields = True
    filter_extra_fields = True
    email = formencode.validators.Email(not_empty=True)

class FormController(BaseController):
    def form(self):
        print 'Params from display method:', request.params
        return render('/form.mako')
    @validate(schema=EmailForm(), form='form')
    def email(self):
        print 'Params from submit method:', request.params
        return 'Your email is: %s' % self.form_result.get('email')

form.mako:
---------------
${h.form(h.url_for(action='email', avar='dummy'), method='post')}
Email Address: ${h.text('email')}
${h.submit('submit', 'Submit')}
${h.hidden('hidden', 'Hidden')}
${h.end_form()}

Cheers ................................................. John Dickson

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to