Tornado and WTForms

I am using WTForms for the first time. Using WTForms to Test POST Requests in Tornado The following are my forms.py forms

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: formdata must be a multi-type shell that supports the getlist method.

How can I do this job?

+6
source share
3 answers

wtforms tornado 0.0.1

Extensions WTForms for Tornado.

 pip install wtforms-tornado 

WTForms-Tornado

+7
source

You will need an object that can translate a Tornado form object into something that 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 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 the # way it 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 will do something like:

 self.form = TornadoFormMultiDict(self) 

Note. I think this is adapted from the mailing list topic on this .

+2
source

I did not find a replacement for the basic html form contained in the Tornado template with the WTForms form as intuitive as I could hope for.

Here is an example of a very simple form using wtforms-tornado :

Template:

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="en"> <head> <meta charset="utf-8"> <title>A Simple Form</title> <meta name="description" content="Submit Track to Infinite Glitch"> </head> <body> <p><h1>Submit Info</h1></p> <form enctype="multipart/form-data" action="/simple" method="post"> {{ form.name }}<br/> {{ form.email }}<br/> {{ form.message }}<br/> <input type="submit"/> </form> </body> </html> 

Application Code:

 import wtforms from wtforms_tornado import Form class EasyForm(Form): name = wtforms.TextField('name', validators=[wtforms.validators.DataRequired()], default=u'test') email = wtforms.TextField('email', validators=[wtforms.validators.Email(), wtforms.validators.DataRequired()]) message = wtforms.TextAreaField('message', validators=[wtforms.validators.DataRequired()]) class SimpleForm(tornado.web.RequestHandler): def get(self): form = EasyForm() self.write(templates.load("simpleform.html").generate(compiled=compiled, form=form)) def post(self): form = EasyForm(self.request.arguments) details = ''; if form.validate(): for f in self.request.arguments: details += "<hr/>" + self.get_argument(f, default=None, strip=False) self.write(details) else: self.set_status(400) self.write(form.errors) if __name__ == "__main__": application = tornado.web.Application( tornadio2.TornadioRouter(SocketConnection).apply_routes([ (r"/simple", SimpleForm), ]), ) application.listen(8888) tornado.ioloop.IOLoop.instance().start() 
0
source

Source: https://habr.com/ru/post/944565/


All Articles