2013-05-08 13 views
6

Sto utilizzando WTForms per la prima volta. Utilizzando WTForms per convalidare le richieste POST in Tornado Sotto è il mio forme forms.pyTornado e WTForms

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

Nel gestore tonado ho

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

Il messaggio di errore che ottengo è: formdata dovrebbe essere un wrapper di tipo multidict che supporta il metodo "lista" "

Come posso fare questo lavoro?

risposta

7

wtforms-tornado 0.0.1

WTForms estensioni per Tornado.

pip install wtforms-tornado 

WTForms-Tornado

2

Avrete bisogno di un oggetto che possa tradurre l'oggetto del modulo Tornado in qualcosa che WTForms si aspetta. Io uso questo:

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) 

Poi, nel tuo gestore di base, devi fare qualcosa di simile:

self.form = TornadoFormMultiDict(self) 

Nota: Penso che questo tratto da un mailing list topic on this subject.

0

non ho trovato la sostituzione di un modulo HTML di base contenuta all'interno di un modello di Tornado con WTForms formano intuitivo come avrei potuto sperare.

Ecco un esempio di una forma molto semplice utilizzando wtforms-tornado:

Il modello:

<!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>  

Il codice app:

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

Ciao, si può completare le importazioni mancanti da 'auto .write (templates.load ("simpleform.html"). generate (compiled = compiled, form = form)) 'in modo che il codice diventi eseguibile? – kardaj

+0

Al momento non sto usando Tornado, quindi dovrò verificarlo un'altra volta. – MikeiLL