Pylons FormEncode与表单元素数组

2 投票
2 回答
2855 浏览
提问于 2025-04-15 12:15

我有一个用Pylons框架做的应用,正在用FormEncode和HtmlFill来处理我的表单。在我的模板(Mako)里,有一组文本输入框。

  <tr>
    <td>Yardage</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
    <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
  </tr>

不过,我一直搞不清楚怎么去验证这些输入框的内容。这里是我Schema里相关的部分:

yardage = formencode.ForEach(formencode.validators.Int())

我想验证这些输入框里的内容是否都是整数(Int)。但是,这些输入框并没有进行任何验证。

更新
根据要求,这里是这个控制器的操作代码。我知道它之前是可以工作的,因为我能验证其他表单字段。

    def submit(self):
        schema = CourseForm()
        try:
            c.form_result = schema.to_python(dict(request.params))
        except formencode.Invalid, error:
            c.form_result = error.value
            c.form_errors = error.error_dict or {}
            c.heading = 'Add a course'
            html = render('/derived/course/add.html')
            return htmlfill.render(
                html,
                defaults = c.form_result,
                errors = c.form_errors 
                )
        else:
            h.redirect_to(controler='course', action='view')

更新
在IRC上有人建议我把元素的名字从yardage[]改成yardage,但没有效果。它们应该都是整数,但如果我在其中一个输入框里填入字母f,系统并没有把它判定为无效。正如我之前说的,我可以验证其他表单字段。下面是我的整个schema。

import formencode

class CourseForm(formencode.Schema):
    allow_extra_fields = True
    filter_extra_fields = True
    name = formencode.validators.NotEmpty(messages={'empty': 'Name must not be empty'})
    par = formencode.ForEach(formencode.validators.Int())
    yardage = formencode.ForEach(formencode.validators.Int())

2 个回答

1
c.form_result = schema.to_python(request.params) - (without dict)

看起来运行得不错。

5

结果发现我想做的事情并不完全正确。

模板:

<tr>
  <td>Yardage</td>
  % for hole in range(9):
  <td>${h.text('hole-%s.yardage'%(hole), maxlength=3, size=3)}</td>
  % endfor
</tr>

(一开始就应该用循环来做。)你会注意到第一个元素的名字会变成 hole-1.yardage。接下来我会用 FormEncode.variabledecode 把它转换成一个字典。这一步是在

模式:

import formencode

class HoleSchema(formencode.Schema):
    allow_extra_fields = False
    yardage = formencode.validators.Int(not_empty=True)
    par = formencode.validators.Int(not_empty=True)

class CourseForm(formencode.Schema):
    allow_extra_fields = True
    filter_extra_fields = True
    name = formencode.validators.NotEmpty(messages={'empty': 'Name must not be empty'})
    hole = formencode.ForEach(HoleSchema())

HoleSchema 会验证 hole-#.parhole-#.yardage 这两个值是否都是整数,并且不能为空。 formencode.ForEach 让我可以把 HoleSchema 应用到我通过将 variable_decode=True 传给 @validate 装饰器得到的字典上。

这是我在

控制器中的 submit 动作:

@validate(schema=CourseForm(), form='add', post_only=False, on_get=True, 
          auto_error_formatter=custom_formatter,
          variable_decode=True)
def submit(self):
    # Do whatever here.
    return 'Submitted!'

使用 @validate 装饰器可以让验证和填写表单的过程变得更简单。 variable_decode=True 非常重要,否则字典就不会正确创建。

撰写回答