Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tornado and WTForms

I am using WTForms for the first time. Using WTForms to validate POST requests in Tornado Below is my forms forms.py

class UserForm(Form):
    user = TextField('user', [validators.Length(min=23, max=23)])

In the tonado handler I have

def post(self):
    form = UserForm(self.request.body)

The error message i get is: formdata should be a multidict-type wrapper that supports the 'getlist' method"

How could I make this work?

like image 518
Joel James Avatar asked May 08 '13 19:05

Joel James


2 Answers

wtforms-tornado 0.0.1

WTForms extensions for Tornado.

pip install wtforms-tornado

WTForms-Tornado

like image 159
daniel__ Avatar answered Sep 19 '22 09:09

daniel__


You'll need an object that can translate the Tornado form object into something WTForms expects. I use this:

class TornadoFormMultiDict(object): 
"""Wrapper class to provide form values to wtforms.Form

This class is tightly coupled to a request handler, and more importantly one of our BaseHandlers
which has a 'context'. At least if you want to use the save/load functionality.

Some of this more difficult that it otherwise seems like it should be because of nature
of how tornado handles it's form input.
"""
def __init__(self, handler): 
    # We keep a weakref to prevent circular references
    # This object is tightly coupled to the handler... which certainly isn't nice, but it's the
    # way it's gonna have to be for now.
    self.handler = weakref.ref(handler)

@property
def _arguments(self):        
    return self.handler().request.arguments

def __iter__(self): 
    return iter(self._arguments) 

def __len__(self):
    return len(self._arguments)

def __contains__(self, name): 
    # We use request.arguments because get_arguments always returns a 
    # value regardless of the existence of the key. 
    return (name in self._arguments)

def getlist(self, name): 
    # get_arguments by default strips whitespace from the input data, 
    # so we pass strip=False to stop that in case we need to validate 
    # on whitespace. 
    return self.handler().get_arguments(name, strip=False) 

def __getitem__(self, name):
    return self.handler().get_argument(name)

Then in your base handler, you'd do something like:

self.form = TornadoFormMultiDict(self)

Note: I think this adapted from a mailing list topic on this subject.

like image 25
rhettg Avatar answered Sep 17 '22 09:09

rhettg