【问题标题】:Tornado and WTForms龙卷风和 WTForms
【发布时间】:2013-05-08 19:41:57
【问题描述】:

我是第一次使用 WTForms。 在 Tornado 中使用 WTForms 验证 POST 请求 以下是我的表格 forms.py

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

在我的 tonado 处理程序中

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

我得到的错误信息是: formdata 应该是一个支持 'getlist' 方法的多字典类型包装器"

我怎样才能做到这一点?

【问题讨论】:

    标签: python forms python-2.7 tornado wtforms


    【解决方案1】:

    wtforms-tornado 0.0.1

    Tornado 的 WTForms 扩展。

    pip install wtforms-tornado
    

    WTForms-Tornado

    【讨论】:

      【解决方案2】:

      您需要一个可以将 Tornado 表单对象转换为 WTForms 期望的对象的对象。我用这个:

      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)
      

      然后在您的基本处理程序中,您会执行以下操作:

      self.form = TornadoFormMultiDict(self)
      

      注意:我认为这改编自 mailing list topic on this subject。

      【讨论】:

        【解决方案3】:

        我没有发现用 WTForms 表单替换 Tornado 模板中包含的基本 html 表单,并没有像我希望的那样直观。

        这是一个使用wtforms-tornado的非常简单的表单示例:

        模板:

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

        应用代码:

        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()
        

        【讨论】:

        • 嗨,你能不能补全来自`self.write(templates.load("simpleform.html").generate(compiled=compiled, form=form))`的缺失导入,使代码变成可以运行吗?
        • 目前根本不使用 Tornado,因此必须在其他时候检查一下。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-27
        • 1970-01-01
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多