WTForms: passing form values back to the user on post

When both the GET and POST methods are in the same handler class, and I want to populate form fields with user input after failed form validation, I do this...

Class CommentHandler(BaseHandler):
    def get(self, form=None):
        if form is None: # create new form unless populated form is passed in
            form = CommentForm()
        # query DB and create template context
        self.render('page.html', **context)

    def post(self):
        form = CommentForm(self.request.POST)
        if form.validate():
            # populate entity with form data and save to DB
            return self.redirect_to('page')
        self.get(form=form) # pass populated form back to user for editing

I don't know if this is the best way to get form data back to the user, but it seems to work. My question is: how do I pass that data back into the form if the GET and POST methods are in different handler classes?

class PageHandler(BaseHandler):
    def get(self):
        # displays form to user

class CommentHandler(BaseHandler):
    def post(self):
        # processes POSTed form data...
        # but if form.validate() fails,
        # how can I pass the form data back to the user
        # so they can edit their form input?

Answers


When you post and call validate() WTForms binds the form encoded data to the Form instance. An http POST can return a response just like a GET this is why you sometimes get those funny messages in your browser when a server application has failed validation and you try to refresh. Its because the refresh action is going to invoke the GET processing pipeline and you will lose your POST data.

What you need to do instead of delegating back to the get implementation you just need to render a response from your post implementation that passes Form instance with the data bound to it back in the response. If you have set your template up in the recommended way the data will automatically show up in the appropriate fields. Below is a snippet of what your Handler might look like.

def post(self):

    form = CommentForm(self.request.POST)

    if form.validate():
        # populate entity with form data and save to DB
        return self.redirect_to('page')

    # If we are here it means we failed validation
    # We need to send back the data the use supplied 
    # with error messages so we can re-render the form
    # with their data and error messages indicating why
    # it was rejected.

    self.render('page.html', form=form) # pass populated form back to user for editing

This of course assumes that your page.html knows what to do with the Form instance.


Here's one workflow that may help to solve your problem. I chose to provide a workflow instead of a specific code snippet in order to avoid being too prescriptive in the technology you use to solve the problem.

GET
if session contains form data:
  add form data from session to template context
display form

POST
if form validates:
  clear this form data from session
  save to db
else:
  save form data to session
  redirect to GET handler

Need Your Help

How to retrieve filepath relatively to a given directory in C

c algorithm filesystems posix

I'm looking for an efficient way to convert absolute filepath to a path relative to a specific directory.